예제 #1
0
        // parameters:
        //      style    风格。如果为 GUI,表示会自动添加 Idle 事件,并在其中执行 Application.DoEvents
        public RmsChannel GetChannel(
            RmsChannelCollection channels,
            string strServerUrl)
        {
            if (_disabled)
            {
                return(null);
            }

            RmsChannel channel = channels.GetChannel(strServerUrl);

            this.Add(channel);
            // TODO: 检查数组是否溢出
            return(channel);
        }
예제 #2
0
        // 创建数据库
        // parameters:
        //      strLibraryCodeList  当前用户的管辖分馆代码列表
        //      bRecreate   是否为重新创建?如果为重新创建,则允许已经存在定义;如果不是重新创建,即首次创建,则不允许已经存在定义
        //                  注: 重新创建的意思, 是 library.xml 中有定义,但 dp2kernel 中没有对应的数据库,要根据定义重新创建这些 dp2kernel 数据库
        int CreateDatabase(
            RmsChannelCollection Channels,
            string strLibraryCodeList,
            string strDatabaseInfo,
            bool bRecreate,
            out string strOutputInfo,
            out string strError)
        {
            strOutputInfo = "";
            strError = "";

            int nRet = 0;

            List<string> created_dbnames = new List<string>();  // 过程中,已经创建的数据库名

            bool bDbChanged = false;    // 数据库名是否发生过改变?或者新创建过数据库? 如果发生过,需要重新初始化kdbs

            XmlDocument dom = new XmlDocument();
            try
            {
                dom.LoadXml(strDatabaseInfo);
            }
            catch (Exception ex)
            {
                strError = "strDatabaseInfo内容装入XMLDOM时出错: " + ex.Message;
                return -1;
            }

            RmsChannel channel = Channels.GetChannel(this.WsUrl);

            XmlNodeList nodes = dom.DocumentElement.SelectNodes("database");
            for (int i = 0; i < nodes.Count; i++)
            {
                XmlNode node = nodes[i];
                string strType = DomUtil.GetAttr(node, "type").ToLower();

                string strName = DomUtil.GetAttr(node, "name");

                // 创建书目数据库
                if (strType == "biblio")
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许创建或重新创建书目库";
                        return -1;
                    }

                    if (this.TestMode == true)
                    {
                        XmlNodeList existing_nodes = this.LibraryCfgDom.DocumentElement.SelectNodes("itemdbgroup/database");
                        if (existing_nodes.Count >= 4)
                        {
                            strError = "dp2Library XE 评估模式下只能创建最多 4 个书目库";
                            goto ERROR1;
                        }
                    }

                    // 2009/11/13
                    XmlNode exist_database_node = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@biblioDbName='"+strName+"']");
                    if (bRecreate == true && exist_database_node == null)
                    {
                        strError = "library.xml中并不存在书目库 '"+strName+"' 的定义,无法进行重新创建";
                        goto ERROR1;
                    }

                    string strSyntax = DomUtil.GetAttr(node, "syntax");
                    if (String.IsNullOrEmpty(strSyntax) == true)
                        strSyntax = "unimarc";

                    // usage: book series
                    string strUsage = DomUtil.GetAttr(node, "usage");
                    if (String.IsNullOrEmpty(strUsage) == true)
                        strUsage = "book";

                    // 2009/10/23
                    string strRole = DomUtil.GetAttr(node, "role");

                    if (bRecreate == false)
                    {
                        // 检查cfgdom中是否已经存在同名的书目库
                        if (this.IsBiblioDbName(strName) == true)
                        {
                            strError = "书目库 '" + strName + "' 的定义已经存在,不能重复创建";
                            goto ERROR1;
                        }
                    }

                    // 检查dp2kernel中是否有和书目库同名的数据库存在
                    {
                        // 数据库是否已经存在?
                        // return:
                        //      -1  error
                        //      0   not exist
                        //      1   exist
                        //      2   其他类型的同名对象已经存在
                        nRet = IsDatabaseExist(
                            channel,
                            strName,
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;
                        if (nRet >= 1)
                            goto ERROR1;
                    }

                    string strEntityDbName = DomUtil.GetAttr(node, "entityDbName");

                    string strOrderDbName = DomUtil.GetAttr(node, "orderDbName");

                    string strIssueDbName = DomUtil.GetAttr(node, "issueDbName");

                    string strCommentDbName = DomUtil.GetAttr(node, "commentDbName");

                    if (strEntityDbName == "<default>")
                        strEntityDbName = strName + "实体";

                    if (strOrderDbName == "<default>")
                        strOrderDbName = strName + "订购";

                    if (strIssueDbName == "<default>")
                        strIssueDbName = strName + "期";

                    if (strCommentDbName == "<default>")
                        strCommentDbName = strName + "评注";

                    string strInCirculation = DomUtil.GetAttr(node, "inCirculation");
                    if (String.IsNullOrEmpty(strInCirculation) == true)
                        strInCirculation = "true";  // 缺省为true

                    string strUnionCatalogStyle = DomUtil.GetAttr(node, "unionCatalogStyle");

                    string strReplication = DomUtil.GetAttr(node, "replication");

                    if (String.IsNullOrEmpty(strEntityDbName) == false)
                    {
                        if (bRecreate == false)
                        {
                            // 检查cfgdom中是否已经存在同名的实体库
                            if (this.IsItemDbName(strEntityDbName) == true)
                            {
                                strError = "实体库 '" + strEntityDbName + "' 的定义已经存在,不能重复创建";
                                goto ERROR1;
                            }
                        }

                        // 数据库是否已经存在?
                        // return:
                        //      -1  error
                        //      0   not exist
                        //      1   exist
                        //      2   其他类型的同名对象已经存在
                        nRet = IsDatabaseExist(
                            channel,
                            strEntityDbName,
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;
                        if (nRet >= 1)
                            goto ERROR1;
                    }

                    if (String.IsNullOrEmpty(strOrderDbName) == false)
                    {
                        if (bRecreate == false)
                        {
                            // 检查cfgdom中是否已经存在同名的订购库
                            if (this.IsOrderDbName(strOrderDbName) == true)
                            {
                                strError = "订购库 '" + strOrderDbName + "' 的定义已经存在,不能重复创建";
                                goto ERROR1;
                            }
                        }

                        // 数据库是否已经存在?
                        // return:
                        //      -1  error
                        //      0   not exist
                        //      1   exist
                        //      2   其他类型的同名对象已经存在
                        nRet = IsDatabaseExist(
                            channel,
                            strOrderDbName,
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;
                        if (nRet >= 1)
                            goto ERROR1;
                    }


                    if (String.IsNullOrEmpty(strIssueDbName) == false)
                    {
                        if (bRecreate == false)
                        {
                            // 检查cfgdom中是否已经存在同名的期库
                            if (this.IsOrderDbName(strIssueDbName) == true)
                            {
                                strError = "期库 '" + strIssueDbName + "' 的定义已经存在,不能重复创建";
                                goto ERROR1;
                            }
                        }

                        // 数据库是否已经存在?
                        // return:
                        //      -1  error
                        //      0   not exist
                        //      1   exist
                        //      2   其他类型的同名对象已经存在
                        nRet = IsDatabaseExist(
                            channel,
                            strIssueDbName,
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;
                        if (nRet >= 1)
                            goto ERROR1;
                    }

                    if (String.IsNullOrEmpty(strCommentDbName) == false)
                    {
                        if (bRecreate == false)
                        {
                            // 检查cfgdom中是否已经存在同名的评注库
                            if (this.IsCommentDbName(strCommentDbName) == true)
                            {
                                strError = "评注库 '" + strCommentDbName + "' 的定义已经存在,不能重复创建";
                                goto ERROR1;
                            }
                        }

                        // 数据库是否已经存在?
                        // return:
                        //      -1  error
                        //      0   not exist
                        //      1   exist
                        //      2   其他类型的同名对象已经存在
                        nRet = IsDatabaseExist(
                            channel,
                            strCommentDbName,
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;
                        if (nRet >= 1)
                            goto ERROR1;
                    }

                    // 开始创建

                    // 创建书目库
                    string strTemplateDir = this.DataDir + "\\templates\\" + "biblio_" + strSyntax + "_" + strUsage;

                    // 根据预先的定义,创建一个数据库
                    nRet = CreateDatabase(channel,
                        strTemplateDir,
                        strName,
                        out strError);
                    if (nRet == -1)
                        goto ERROR1;

                    created_dbnames.Add(strName);

                    bDbChanged = true;

                    // 创建实体库
                    if (String.IsNullOrEmpty(strEntityDbName) == false)
                    {
                        strTemplateDir = this.DataDir + "\\templates\\" + "item";

                        // 根据预先的定义,创建一个数据库
                        nRet = CreateDatabase(channel,
                            strTemplateDir,
                            strEntityDbName,
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;

                        created_dbnames.Add(strEntityDbName);

                        bDbChanged = true;
                    }

                    // 创建订购库
                    if (String.IsNullOrEmpty(strOrderDbName) == false)
                    {
                        strTemplateDir = this.DataDir + "\\templates\\" + "order";

                        // 根据预先的定义,创建一个数据库
                        nRet = CreateDatabase(channel,
                            strTemplateDir,
                            strOrderDbName,
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;
                        created_dbnames.Add(strOrderDbName);

                        bDbChanged = true;
                    }

                    // 创建期库
                    if (String.IsNullOrEmpty(strIssueDbName) == false)
                    {
                        strTemplateDir = this.DataDir + "\\templates\\" + "issue";

                        // 根据预先的定义,创建一个数据库
                        nRet = CreateDatabase(channel,
                            strTemplateDir,
                            strIssueDbName,
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;
                        created_dbnames.Add(strIssueDbName);

                        bDbChanged = true;
                    }

                    // 创建评注库
                    if (String.IsNullOrEmpty(strCommentDbName) == false)
                    {
                        strTemplateDir = this.DataDir + "\\templates\\" + "comment";

                        // 根据预先的定义,创建一个数据库
                        nRet = CreateDatabase(channel,
                            strTemplateDir,
                            strCommentDbName,
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;
                        created_dbnames.Add(strCommentDbName);

                        bDbChanged = true;
                    }

                    // 在CfgDom中增加相关的配置信息
                    XmlNode root = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup");
                    if (root == null)
                    {
                        root = this.LibraryCfgDom.CreateElement("itemdbgroup");
                        this.LibraryCfgDom.DocumentElement.AppendChild(root);
                    }

                    XmlNode nodeNewDatabase = null;

                    if (bRecreate == false)
                    {
                        nodeNewDatabase = this.LibraryCfgDom.CreateElement("database");
                        root.AppendChild(nodeNewDatabase);
                    }
                    else
                    {
                        nodeNewDatabase = exist_database_node;
                    }

                    DomUtil.SetAttr(nodeNewDatabase, "name", strEntityDbName);
                    DomUtil.SetAttr(nodeNewDatabase, "biblioDbName", strName);
                    if (String.IsNullOrEmpty(strOrderDbName) == false)
                    {
                        DomUtil.SetAttr(nodeNewDatabase, "orderDbName", strOrderDbName);
                    }
                    if (String.IsNullOrEmpty(strIssueDbName) == false)
                    {
                        DomUtil.SetAttr(nodeNewDatabase, "issueDbName", strIssueDbName);
                    }
                    if (String.IsNullOrEmpty(strCommentDbName) == false)
                    {
                        DomUtil.SetAttr(nodeNewDatabase, "commentDbName", strCommentDbName);
                    }
                    DomUtil.SetAttr(nodeNewDatabase, "syntax", strSyntax);

                    // 2009/10/23
                    DomUtil.SetAttr(nodeNewDatabase, "role", strRole);

                    DomUtil.SetAttr(nodeNewDatabase, "inCirculation", strInCirculation);

                    // 2012/4/30
                    if (string.IsNullOrEmpty(strUnionCatalogStyle) == false)
                        DomUtil.SetAttr(nodeNewDatabase, "unionCatalogStyle", strUnionCatalogStyle);

                    if (string.IsNullOrEmpty(strReplication) == false)
                        DomUtil.SetAttr(nodeNewDatabase, "replication", strReplication);

                    // <itemdbgroup>内容更新,刷新配套的内存结构
                    nRet = this.LoadItemDbGroupParam(this.LibraryCfgDom,
                        out strError);
                    if (nRet == -1)
                    {
                        this.WriteErrorLog(strError);
                        goto ERROR1;
                    }

                    this.Changed = true;
                    this.ActivateManagerThread();

                    created_dbnames.Clear();

                    continue;
                } // end of type biblio
                else if (strType == "entity")
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许创建或重新创建实体库";
                        return -1;
                    }
                    // TODO: 增加recreate能力

                    // 单独创建实体库
                    string strBiblioDbName = DomUtil.GetAttr(node, "biblioDbName");
                    if (String.IsNullOrEmpty(strBiblioDbName) == true)
                    {
                        strError = "请求创建实体库的<database>元素中,应包含biblioDbName属性";
                        goto ERROR1;
                    }

                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@biblioDbName='" + strBiblioDbName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strBiblioDbName + "' 的书目库(biblioDbName属性)相关<database>元素没有找到,无法在其下创建实体库 " + strName;
                        goto ERROR1;
                    }

                    string strOldEntityDbName = DomUtil.GetAttr(nodeDatabase,
                        "name");
                    if (strOldEntityDbName == strName)
                    {
                        strError = "从属于书目库 '" + strBiblioDbName + "' 的实体库 '" + strName + "' 定义已经存在,不能重复创建";
                        goto ERROR1;
                    }

                    if (String.IsNullOrEmpty(strOldEntityDbName) == false)
                    {
                        strError = "要创建从属于书目库 '" + strBiblioDbName + "' 的新实体库 '" + strName + "',必须先删除已经存在的实体库 '"
                            + strOldEntityDbName + "'";
                        goto ERROR1;
                    }

                    string strTemplateDir = this.DataDir + "\\templates\\" + "item";

                    // 根据预先的定义,创建一个数据库
                    nRet = CreateDatabase(channel,
                        strTemplateDir,
                        strName,
                        out strError);
                    if (nRet == -1)
                        goto ERROR1;

                    created_dbnames.Add(strName);

                    bDbChanged = true;

                    DomUtil.SetAttr(nodeDatabase, "name", strName);

                    // 2008/12/4
                    // <itemdbgroup>内容更新,刷新配套的内存结构
                    nRet = this.LoadItemDbGroupParam(this.LibraryCfgDom,
                        out strError);
                    if (nRet == -1)
                    {
                        this.WriteErrorLog(strError);
                        goto ERROR1;
                    }

                    this.Changed = true;
                }
                else if (strType == "order")
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许创建或重新创建订购库";
                        return -1;
                    }
                    // TODO: 增加recreate能力

                    // 单独创建订购库
                    string strBiblioDbName = DomUtil.GetAttr(node, "biblioDbName");
                    if (String.IsNullOrEmpty(strBiblioDbName) == true)
                    {
                        strError = "创建订购库的<database>元素中,应包含biblioDbName属性";
                        goto ERROR1;
                    }

                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@biblioDbName='" + strBiblioDbName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strBiblioDbName + "' 的书目库(biblioDbName属性)相关<database>元素没有找到,无法在其下创建订购库 " + strName;
                        goto ERROR1;
                    }

                    string strOldOrderDbName = DomUtil.GetAttr(nodeDatabase,
                        "orderDbName");
                    if (strOldOrderDbName == strName)
                    {
                        strError = "从属于书目库 '" + strBiblioDbName + "' 的订购库 '" + strName + "' 定义已经存在,不能重复创建";
                        goto ERROR1;
                    }

                    if (String.IsNullOrEmpty(strOldOrderDbName) == false)
                    {
                        strError = "要创建从属于书目库 '" + strBiblioDbName + "' 的新订购库 '" + strName + "',必须先删除已经存在的订购库 '"
                            + strOldOrderDbName + "'";
                        goto ERROR1;
                    }

                    string strTemplateDir = this.DataDir + "\\templates\\" + "order";

                    // 根据预先的定义,创建一个数据库
                    nRet = CreateDatabase(channel,
                        strTemplateDir,
                        strName,
                        out strError);
                    if (nRet == -1)
                        goto ERROR1;
                    created_dbnames.Add(strName);

                    bDbChanged = true;

                    DomUtil.SetAttr(nodeDatabase, "orderDbName", strName);

                    // 2008/12/4
                    // <itemdbgroup>内容更新,刷新配套的内存结构
                    nRet = this.LoadItemDbGroupParam(this.LibraryCfgDom,
                        out strError);
                    if (nRet == -1)
                    {
                        this.WriteErrorLog(strError);
                        goto ERROR1;
                    }

                    this.Changed = true;
                }
                else if (strType == "issue")
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许创建或重新创建期库";
                        return -1;
                    }
                    // TODO: 增加recreate能力

                    // 单独创建期库
                    string strBiblioDbName = DomUtil.GetAttr(node, "biblioDbName");
                    if (String.IsNullOrEmpty(strBiblioDbName) == true)
                    {
                        strError = "创建期库的<database>元素中,应包含biblioDbName属性";
                        goto ERROR1;
                    }

                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@biblioDbName='" + strBiblioDbName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strBiblioDbName + "' 的书目库(biblioDbName属性)相关<database>元素没有找到,无法在其下创建期库 " + strName;
                        goto ERROR1;
                    }

                    string strOldIssueDbName = DomUtil.GetAttr(nodeDatabase,
                        "issueDbName");
                    if (strOldIssueDbName == strName)
                    {
                        strError = "从属于书目库 '"+strBiblioDbName+"' 的期库 '" + strName + "' 定义已经存在,不能重复创建";
                        goto ERROR1;
                    }

                    if (String.IsNullOrEmpty(strOldIssueDbName) == false)
                    {
                        strError = "要创建从属于书目库 '" + strBiblioDbName + "' 的新期库 '" + strName + "',必须先删除已经存在的期库 '"
                            +strOldIssueDbName+"'";
                        goto ERROR1;
                    }

                    string strTemplateDir = this.DataDir + "\\templates\\" + "issue";

                    // 根据预先的定义,创建一个数据库
                    nRet = CreateDatabase(channel,
                        strTemplateDir,
                        strName,
                        out strError);
                    if (nRet == -1)
                        goto ERROR1;
                    created_dbnames.Add(strName);

                    bDbChanged = true;

                    DomUtil.SetAttr(nodeDatabase, "issueDbName", strName);

                    // 2008/12/4
                    // <itemdbgroup>内容更新,刷新配套的内存结构
                    nRet = this.LoadItemDbGroupParam(this.LibraryCfgDom,
                        out strError);
                    if (nRet == -1)
                    {
                        this.WriteErrorLog(strError);
                        goto ERROR1;
                    }

                    this.Changed = true;
                }
                else if (strType == "comment")
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许创建或重新创建评注库";
                        return -1;
                    }
                    // TODO: 增加recreate能力

                    // 单独创建评注库
                    string strBiblioDbName = DomUtil.GetAttr(node, "biblioDbName");
                    if (String.IsNullOrEmpty(strBiblioDbName) == true)
                    {
                        strError = "创建评注库的<database>元素中,应包含biblioDbName属性";
                        goto ERROR1;
                    }

                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@biblioDbName='" + strBiblioDbName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strBiblioDbName + "' 的书目库(biblioDbName属性)相关<database>元素没有找到,无法在其下创建评注库 " + strName;
                        goto ERROR1;
                    }

                    string strOldCommentDbName = DomUtil.GetAttr(nodeDatabase,
                        "commentDbName");
                    if (strOldCommentDbName == strName)
                    {
                        strError = "从属于书目库 '" + strBiblioDbName + "' 的评注库 '" + strName + "' 定义已经存在,不能重复创建";
                        goto ERROR1;
                    }

                    if (String.IsNullOrEmpty(strOldCommentDbName) == false)
                    {
                        strError = "要创建从属于书目库 '" + strBiblioDbName + "' 的新评注库 '" + strName + "',必须先删除已经存在的评注库 '"
                            + strOldCommentDbName + "'";
                        goto ERROR1;
                    }

                    string strTemplateDir = this.DataDir + "\\templates\\" + "comment";

                    // 根据预先的定义,创建一个数据库
                    nRet = CreateDatabase(channel,
                        strTemplateDir,
                        strName,
                        out strError);
                    if (nRet == -1)
                        goto ERROR1;
                    created_dbnames.Add(strName);

                    bDbChanged = true;

                    DomUtil.SetAttr(nodeDatabase, "commentDbName", strName);

                    // 2008/12/4
                    // <itemdbgroup>内容更新,刷新配套的内存结构
                    nRet = this.LoadItemDbGroupParam(this.LibraryCfgDom,
                        out strError);
                    if (nRet == -1)
                    {
                        this.WriteErrorLog(strError);
                        goto ERROR1;
                    }

                    this.Changed = true;
                }
                else if (strType == "reader")
                {
                    // 创建读者库

                    // 2009/11/13
                    XmlNode exist_database_node = this.LibraryCfgDom.DocumentElement.SelectSingleNode("readerdbgroup/database[@name='" + strName + "']");
                    if (bRecreate == true && exist_database_node == null)
                    {
                        strError = "library.xml中并不存在读者库 '" + strName + "' 的定义,无法进行重新创建";
                        goto ERROR1;
                    }


                    if (bRecreate == false)
                    {
                        // 检查cfgdom中是否已经存在同名的读者库
                        if (this.IsReaderDbName(strName) == true)
                        {
                            strError = "读者库 '" + strName + "' 的定义已经存在,不能重复创建";
                            goto ERROR1;
                        }
                    }
                    else
                    {
                        if (exist_database_node != null)
                        {
                            string strExistLibraryCode = DomUtil.GetAttr(exist_database_node, "libraryCode");

                            // 2012/9/9
                            // 分馆用户只允许修改馆代码属于管辖分馆的读者库
                            if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                            {
                                if (string.IsNullOrEmpty(strExistLibraryCode) == true
                                    || StringUtil.IsInList(strExistLibraryCode, strLibraryCodeList) == false)
                                {
                                    strError = "重新创建读者库 '"+strName+"' 被拒绝。当前用户只能重新创建图书馆代码完全完全属于 '" + strLibraryCodeList + "' 范围的读者库";
                                    goto ERROR1;
                                }
                            }
                        }
                    }

                    string strLibraryCode = DomUtil.GetAttr(node,
    "libraryCode");

                    // 2012/9/9
                    // 分馆用户只允许处理馆代码为特定范围的读者库
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        if (string.IsNullOrEmpty(strLibraryCode) == true
                            || IsListInList(strLibraryCode, strLibraryCodeList) == false)
                        {
                            strError = "当前用户只能创建馆代码完全属于 '" + strLibraryCodeList + "' 范围内的读者库";
                            return -1;
                        }
                    }

                    // 检查dp2kernel中是否有和读者库同名的数据库存在
                    {
                        // 数据库是否已经存在?
                        // return:
                        //      -1  error
                        //      0   not exist
                        //      1   exist
                        //      2   其他类型的同名对象已经存在
                        nRet = IsDatabaseExist(
                            channel,
                            strName,
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;
                        if (nRet >= 1)
                            goto ERROR1;
                    }

                    string strTemplateDir = this.DataDir + "\\templates\\" + "reader";

                    // 根据预先的定义,创建一个数据库
                    nRet = CreateDatabase(channel,
                        strTemplateDir,
                        strName,
                        out strError);
                    if (nRet == -1)
                        goto ERROR1;
                    created_dbnames.Add(strName);

                    bDbChanged = true;

                    string strInCirculation = DomUtil.GetAttr(node,
                        "inCirculation");
                    if (String.IsNullOrEmpty(strInCirculation) == true)
                        strInCirculation = "true";  // 缺省为true


                    // 检查一个单独的图书馆代码是否格式正确
                    // 要求不能为 '*',不能包含逗号
                    // return:
                    //      -1  校验函数本身出错了
                    //      0   校验正确
                    //      1   校验发现问题。strError中有描述
                    nRet = VerifySingleLibraryCode(strLibraryCode,
        out strError);
                    if (nRet != 0)
                    {
                        strError = "图书馆代码 '" + strLibraryCode + "' 格式错误: " + strError;
                        goto ERROR1;
                    }

                    // 在CfgDom中增加相关的配置信息
                    XmlNode root = this.LibraryCfgDom.DocumentElement.SelectSingleNode("readerdbgroup");
                    if (root == null)
                    {
                        root = this.LibraryCfgDom.CreateElement("readerdbgroup");
                        this.LibraryCfgDom.DocumentElement.AppendChild(root);
                    }

                    XmlNode nodeNewDatabase = null;
                    if (bRecreate == false)
                    {
                        nodeNewDatabase = this.LibraryCfgDom.CreateElement("database");
                        root.AppendChild(nodeNewDatabase);
                    }
                    else
                    {
                        nodeNewDatabase = exist_database_node;
                    }

                    DomUtil.SetAttr(nodeNewDatabase, "name", strName);
                    DomUtil.SetAttr(nodeNewDatabase, "inCirculation", strInCirculation);
                    DomUtil.SetAttr(nodeNewDatabase, "libraryCode", strLibraryCode);    // 2012/9/7

                    // <readerdbgroup>内容更新,刷新配套的内存结构
                    this.LoadReaderDbGroupParam(this.LibraryCfgDom);
                    this.Changed = true;
                }
                else if (strType == "publisher"
                    || strType == "zhongcihao"
                    || strType == "dictionary"
                    || strType == "inventory")
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许创建或重新创建出版者库、种次号库、字典库和盘点库";
                        return -1;
                    }

                    // 看看同名的 publisher/zhongcihao/dictionary/inventory 数据库是否已经存在?
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("utilDb/database[@name='" + strName + "']");
                    if (bRecreate == false)
                    {
                        if (nodeDatabase != null)
                        {
                            strError = strType + "库 '" + strName + "' 的定义已经存在,不能重复创建";
                            goto ERROR1;
                        }
                    }
                    else
                    {
                        if (nodeDatabase == null)
                        {
                            strError = strType + "库 '" + strName + "' 的定义并不存在,无法进行重复创建";
                            goto ERROR1;
                        }
                    }

                    // TODO: 是否限定publisher库只能创建一个?
                    // 而zhongcihao库显然是可以创建多个的

                    // 检查dp2kernel中是否有和 publisher/zhongcihao/dictionary/inventory 库同名的数据库存在
                    {
                        // 数据库是否已经存在?
                        // return:
                        //      -1  error
                        //      0   not exist
                        //      1   exist
                        //      2   其他类型的同名对象已经存在
                        nRet = IsDatabaseExist(
                            channel,
                            strName,
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;
                        if (nRet >= 1)
                            goto ERROR1;
                    }


                    string strTemplateDir = this.DataDir + "\\templates\\" + strType;

                    // 根据预先的定义,创建一个数据库
                    nRet = CreateDatabase(channel,
                        strTemplateDir,
                        strName,
                        out strError);
                    if (nRet == -1)
                        goto ERROR1;
                    created_dbnames.Add(strName);
                    bDbChanged = true;  // 2012/12/12

                    // 在CfgDom中增加相关的配置信息
                    XmlNode root = this.LibraryCfgDom.DocumentElement.SelectSingleNode("utilDb");
                    if (root == null)
                    {
                        root = this.LibraryCfgDom.CreateElement("utilDb");
                        this.LibraryCfgDom.DocumentElement.AppendChild(root);
                    }

                    XmlNode nodeNewDatabase = null;
                    if (bRecreate == false)
                    {
                        nodeNewDatabase = this.LibraryCfgDom.CreateElement("database");
                        root.AppendChild(nodeNewDatabase);
                    }
                    else
                    {
                        nodeNewDatabase = nodeDatabase;
                    }

                    DomUtil.SetAttr(nodeNewDatabase, "name", strName);
                    DomUtil.SetAttr(nodeNewDatabase, "type", strType);
                    this.Changed = true;
                }
                else if (strType == "arrived")
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许创建或重新创建预约到书库";
                        return -1;
                    }

                    // 看看同名的 arrived 数据库是否已经存在?
                    if (bRecreate == false)
                    {
                        if (this.ArrivedDbName == strName)
                        {
                            strError = "预约到书库 '" + strName + "' 的定义已经存在,不能重复创建";
                            goto ERROR1;
                        }
                    }

                    if (String.IsNullOrEmpty(this.ArrivedDbName) == false)
                    {
                        if (bRecreate == true)
                        {
                            if (this.ArrivedDbName != strName)
                            {
                                strError = "已经存在一个预约到书库 '" + this.ArrivedDbName + "' 定义,和您请求重新创建的预约到书库 '" + strName + "' 名字不同。无法直接进行重新创建。请先删除已存在的数据库再进行创建";
                                goto ERROR1;
                            }
                        }
                        else
                        {
                            strError = "要创建新的预约到书库 '" + strName + "',必须先删除已经存在的预约到书库 '"
                                + this.ArrivedDbName + "'";
                            goto ERROR1;
                        }
                    }

                    // 检查dp2kernel中是否有和arrived库同名的数据库存在
                    {
                        // 数据库是否已经存在?
                        // return:
                        //      -1  error
                        //      0   not exist
                        //      1   exist
                        //      2   其他类型的同名对象已经存在
                        nRet = IsDatabaseExist(
                            channel,
                            strName,
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;
                        if (nRet >= 1)
                            goto ERROR1;
                    }

                    string strTemplateDir = this.DataDir + "\\templates\\" + "arrived";

                    // 根据预先的定义,创建一个数据库
                    nRet = CreateDatabase(channel,
                        strTemplateDir,
                        strName,
                        out strError);
                    if (nRet == -1)
                        goto ERROR1;
                    created_dbnames.Add(strName);
                    bDbChanged = true;  // 2012/12/12

                    // 在CfgDom中增加相关的配置信息
                    this.ArrivedDbName = strName;
                    this.Changed = true;
                }
                else if (strType == "amerce")
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许创建或重新创建违约金库";
                        return -1;
                    }

                    // 看看同名的amerce数据库是否已经存在?
                    if (bRecreate == false)
                    {
                        if (this.AmerceDbName == strName)
                        {
                            strError = "违约金库 '" + strName + "' 的定义已经存在,不能重复创建";
                            goto ERROR1;
                        }
                    }

                    if (String.IsNullOrEmpty(this.AmerceDbName) == false)
                    {
                        if (bRecreate == true)
                        {
                            if (this.AmerceDbName != strName)
                            {
                                strError = "已经存在一个违约金库 '" + this.AmerceDbName + "' 定义,和您请求重新创建的违约金库 '" + strName + "' 名字不同。无法直接进行重新创建。请先删除已存在的数据库再进行创建";
                                goto ERROR1;
                            }
                        }
                        else
                        {
                            strError = "要创建新的违约金库 '" + strName + "',必须先删除已经存在的违约金库 '"
                                + this.AmerceDbName + "'";
                            goto ERROR1;
                        }
                    }

                    // 检查dp2kernel中是否有和amerce库同名的数据库存在
                    {
                        // 数据库是否已经存在?
                        // return:
                        //      -1  error
                        //      0   not exist
                        //      1   exist
                        //      2   其他类型的同名对象已经存在
                        nRet = IsDatabaseExist(
                            channel,
                            strName,
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;
                        if (nRet >= 1)
                            goto ERROR1;
                    }


                    string strTemplateDir = this.DataDir + "\\templates\\" + "amerce";

                    // 根据预先的定义,创建一个数据库
                    nRet = CreateDatabase(channel,
                        strTemplateDir,
                        strName,
                        out strError);
                    if (nRet == -1)
                        goto ERROR1;
                    created_dbnames.Add(strName);
                    bDbChanged = true;  // 2012/12/12

                    // 在CfgDom中增加相关的配置信息
                    this.AmerceDbName = strName;
                    this.Changed = true;
                }
                else if (strType == "message")
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许创建或重新创建消息库";
                        return -1;
                    }

                    // 看看同名的message数据库是否已经存在?
                    if (bRecreate == false)
                    {
                        if (this.MessageDbName == strName)
                        {
                            strError = "消息库 '" + strName + "' 的定义已经存在,不能重复创建";
                            goto ERROR1;
                        }
                    }

                    if (String.IsNullOrEmpty(this.MessageDbName) == false)
                    {
                        if (bRecreate == true)
                        {
                            if (this.MessageDbName != strName)
                            {
                                strError = "已经存在一个消息库 '" + this.MessageDbName + "' 定义,和您请求重新创建的消息库 '" + strName + "' 名字不同。无法直接进行重新创建。请先删除已存在的数据库再进行创建";
                                goto ERROR1;
                            }
                        }
                        else
                        {
                            strError = "要创建新的消息库 '" + strName + "',必须先删除已经存在的消息库 '"
                                + this.MessageDbName + "'";
                            goto ERROR1;
                        }
                    }

                    // 检查dp2kernel中是否有和message库同名的数据库存在
                    {
                        // 数据库是否已经存在?
                        // return:
                        //      -1  error
                        //      0   not exist
                        //      1   exist
                        //      2   其他类型的同名对象已经存在
                        nRet = IsDatabaseExist(
                            channel,
                            strName,
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;
                        if (nRet >= 1)
                            goto ERROR1;
                    }


                    string strTemplateDir = this.DataDir + "\\templates\\" + "message";

                    // 根据预先的定义,创建一个数据库
                    nRet = CreateDatabase(channel,
                        strTemplateDir,
                        strName,
                        out strError);
                    if (nRet == -1)
                        goto ERROR1;
                    created_dbnames.Add(strName);
                    bDbChanged = true;  // 2012/12/12

                    // 在CfgDom中增加相关的配置信息
                    this.MessageDbName = strName;
                    this.Changed = true;
                }
                else if (strType == "invoice")
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许创建或重新创建发票库";
                        return -1;
                    }

                    // 看看同名的invoice数据库是否已经存在?
                    if (bRecreate == false)
                    {
                        if (this.InvoiceDbName == strName)
                        {
                            strError = "发票库 '" + strName + "' 的定义已经存在,不能重复创建";
                            goto ERROR1;
                        }
                    }

                    if (String.IsNullOrEmpty(this.InvoiceDbName) == false)
                    {
                        if (bRecreate == true)
                        {
                            if (this.InvoiceDbName != strName)
                            {
                                strError = "已经存在一个发票库 '" + this.InvoiceDbName + "' 定义,和您请求重新创建的发票库 '" + strName + "' 名字不同。无法直接进行重新创建。请先删除已存在的数据库再进行创建";
                                goto ERROR1;
                            }
                        }
                        else
                        {
                            strError = "要创建新的发票库 '" + strName + "',必须先删除已经存在的发票库 '"
                                + this.InvoiceDbName + "'";
                            goto ERROR1;
                        }
                    }

                    // 检查dp2kernel中是否有和invoice库同名的数据库存在
                    {
                        // 数据库是否已经存在?
                        // return:
                        //      -1  error
                        //      0   not exist
                        //      1   exist
                        //      2   其他类型的同名对象已经存在
                        nRet = IsDatabaseExist(
                            channel,
                            strName,
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;
                        if (nRet >= 1)
                            goto ERROR1;
                    }


                    string strTemplateDir = this.DataDir + "\\templates\\" + "invoice";

                    // 根据预先的定义,创建一个数据库
                    nRet = CreateDatabase(channel,
                        strTemplateDir,
                        strName,
                        out strError);
                    if (nRet == -1)
                        goto ERROR1;
                    created_dbnames.Add(strName);
                    bDbChanged = true;  // 2012/12/12

                    // 在CfgDom中增加相关的配置信息
                    this.InvoiceDbName = strName;
                    this.Changed = true;
                }
                else
                {
                    strError = "未知的数据库类型 '" + strType + "'";
                    goto ERROR1;
                }

                if (this.Changed == true)
                    this.ActivateManagerThread();

                created_dbnames.Clear();
            }


            Debug.Assert(created_dbnames.Count == 0, "");

            if (bDbChanged == true)
            {
                nRet = InitialKdbs(
                    Channels,
                    out strError);
                if (nRet == -1)
                    return -1;
                // 重新初始化虚拟库定义
                this.vdbs = null;
                nRet = this.InitialVdbs(Channels,
                    out strError);
                if (nRet == -1)
                    return -1;
            }

            return 0;
        ERROR1:
            List<string> error_deleting_dbnames = new List<string>();
            // 将本次已经创建的数据库在返回前删除掉
            for (int i = 0; i < created_dbnames.Count; i++)
            {
                string strDbName = created_dbnames[i];

                string strError_1 = "";

                long lRet = channel.DoDeleteDB(strDbName, out strError_1);
                if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                    continue;
                if (lRet == -1)
                    error_deleting_dbnames.Add(strDbName + "[错误:"+strError_1+"]");
            }

            if (error_deleting_dbnames.Count > 0)
            {
                strError = strError + ";\r\n并在删除刚创建的数据库时发生错误,下列数据库未被删除:" + StringUtil.MakePathList(error_deleting_dbnames);
                return -1;
            }

            return -1;
        }
예제 #3
0
        // 修改数据库
        int ChangeDatabase(
            RmsChannelCollection Channels,
            string strLibraryCodeList,
            string strDatabaseNames,
            string strDatabaseInfo,
            out string strOutputInfo,
            out string strError)
        {
            strOutputInfo = "";
            strError = "";

            int nRet = 0;
            // long lRet = 0;

            bool bDbNameChanged = false;

            XmlDocument dom = new XmlDocument();
            try
            {
                dom.LoadXml(strDatabaseInfo);
            }
            catch (Exception ex)
            {
                strError = "strDatabaseInfo内容装入XMLDOM时出错: " + ex.Message;
                return -1;
            }

            // 核对strDatabaseNames中包含的数据库名数目是否和dom中的<database>元素数相等
            string[] names = strDatabaseNames.Split(new char[] {','});
            XmlNodeList nodes = dom.DocumentElement.SelectNodes("database");
            if (names.Length != nodes.Count)
            {
                strError = "strDatabaseNames参数中包含的数据库名个数 "+names.Length.ToString()+" 和strDatabaseInfo参数中包含的<database>元素数 "+nodes.Count.ToString()+" 不等";
                return -1;
            }

            RmsChannel channel = Channels.GetChannel(this.WsUrl);

            for (int i = 0; i < names.Length; i++)
            {
                string strName = names[i].Trim();
                if (String.IsNullOrEmpty(strName) == true)
                {
                    strError = "strDatabaseNames参数中不能包含空的名字";
                    return -1;
                }

                // 来自strDatabaseInfo
                XmlElement nodeNewDatabase = nodes[i] as XmlElement;

                // 修改书目库名、或者书目库从属的其他数据库名
                if (this.IsBiblioDbName(strName) == true)
                {
                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@biblioDbName='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的书目库(biblioDbName属性)相关<database>元素没有找到";
                        return -1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许修改书目库定义";
                        return -1;
                    }

                    /*
                     * <database>元素中的name/entityDbName/orderDbName/issueDbName
                     * 传递了改名请求。如果属性值为空,不表明要删除数据库,而是该属性无效。
                     * 实际上这里不响应删除数据库的动作,只能改名
                     * 将来可以改造为响应删除数据库的请求,那么,只要属性具备,就有请求。如果不想请求,则不要包含那个属性
                     * */
                    {
                        // 书目库名
                        string strOldBiblioDbName = strName;

                        // 来自strDatabaseInfo
                        string strNewBiblioDbName = DomUtil.GetAttr(nodeNewDatabase,
                            "name");

                        // 如果strNewBiblioDbName为空,表示不想改变名字
                        if (String.IsNullOrEmpty(strNewBiblioDbName) == false
                            && strOldBiblioDbName != strNewBiblioDbName)
                        {
                            if (String.IsNullOrEmpty(strOldBiblioDbName) == true
                                && String.IsNullOrEmpty(strNewBiblioDbName) == false)
                            {
                                strError = "要创建书目库 '" + strNewBiblioDbName + "',请使用create功能,而不能使用change功能";
                                goto ERROR1;
                            }

                            nRet = ChangeDbName(
                                channel,
                                strOldBiblioDbName,
                                strNewBiblioDbName,
                                () => {
                                    DomUtil.SetAttr(nodeDatabase, "biblioDbName", strNewBiblioDbName);
                                    bDbNameChanged = true;
                                    this.Changed = true;
                                },
                                out strError);
                            if (nRet == -1)
                                goto ERROR1;
#if NO
                            bDbNameChanged = true;
                            DomUtil.SetAttr(nodeDatabase, "biblioDbName", strNewBiblioDbName);
                            this.Changed = true;
#endif
                        }
                    }

                    {
                        // 实体库名
                        string strOldEntityDbName = DomUtil.GetAttr(nodeDatabase,
                            "name");

                        // 来自strDatabaseInfo
                        string strNewEntityDbName = DomUtil.GetAttr(nodeNewDatabase,
                            "entityDbName");

                        if (String.IsNullOrEmpty(strNewEntityDbName) == false
                            && strOldEntityDbName != strNewEntityDbName)
                        {
                            if (String.IsNullOrEmpty(strOldEntityDbName) == true
                                && String.IsNullOrEmpty(strNewEntityDbName) == false)
                            {
                                strError = "要创建实体库 '" + strNewEntityDbName + "',请使用create功能,而不能使用change功能";
                                goto ERROR1;
                            }

                            nRet = ChangeDbName(
                                channel,
                                strOldEntityDbName,
                                strNewEntityDbName,
                                () =>
                                {
                                    DomUtil.SetAttr(nodeDatabase, "name", strNewEntityDbName);
                                    bDbNameChanged = true;
                                    this.Changed = true;
                                },
                                out strError);
                            if (nRet == -1)
                                goto ERROR1;

#if NO
                            bDbNameChanged = true;

                            DomUtil.SetAttr(nodeDatabase, "name", strNewEntityDbName);
                            this.Changed = true;
#endif
                        }
                    }


                    {
                        // 订购库名
                        string strOldOrderDbName = DomUtil.GetAttr(nodeDatabase,
                            "orderDbName");

                        // 来自strDatabaseInfo
                        string strNewOrderDbName = DomUtil.GetAttr(nodeNewDatabase,
                            "orderDbName");
                        if (String.IsNullOrEmpty(strNewOrderDbName) == false
                            && strOldOrderDbName != strNewOrderDbName)
                        {
                            if (String.IsNullOrEmpty(strOldOrderDbName) == true
                                && String.IsNullOrEmpty(strNewOrderDbName) == false)
                            {
                                strError = "要创建订购库 '" + strNewOrderDbName + "',请使用create功能,而不能使用change功能";
                                goto ERROR1;
                            }

                            nRet = ChangeDbName(
                                channel,
                                strOldOrderDbName,
                                strNewOrderDbName,
                                () =>
                                {
                                    DomUtil.SetAttr(nodeDatabase, "orderDbName", strNewOrderDbName);
                                    bDbNameChanged = true;
                                    this.Changed = true;
                                },
                                out strError);
                            if (nRet == -1)
                                goto ERROR1;

#if NO
                            bDbNameChanged = true;

                            DomUtil.SetAttr(nodeDatabase, "orderDbName", strNewOrderDbName);
                            this.Changed = true;
#endif
                        }
                    }

                    {
                        // 期库名
                        string strOldIssueDbName = DomUtil.GetAttr(nodeDatabase,
                            "issueDbName");

                        // 来自strDatabaseInfo
                        string strNewIssueDbName = DomUtil.GetAttr(nodeNewDatabase,
                            "issueDbName");
                        if (String.IsNullOrEmpty(strNewIssueDbName) == false
                            && strOldIssueDbName != strNewIssueDbName)
                        {
                            if (String.IsNullOrEmpty(strOldIssueDbName) == true
                                && String.IsNullOrEmpty(strNewIssueDbName) == false)
                            {
                                strError = "要创建期库 '" + strNewIssueDbName + "',请使用create功能,而不能使用change功能";
                                goto ERROR1;
                            }

                            nRet = ChangeDbName(
                                channel,
                                strOldIssueDbName,
                                strNewIssueDbName,
                                () =>
                                {
                                    DomUtil.SetAttr(nodeDatabase, "issueDbName", strNewIssueDbName);
                                    bDbNameChanged = true;
                                    this.Changed = true;
                                },
                                out strError);
                            if (nRet == -1)
                                goto ERROR1;

#if NO
                            bDbNameChanged = true;

                            DomUtil.SetAttr(nodeDatabase, "issueDbName", strNewIssueDbName);
                            this.Changed = true;
#endif
                        }
                    }


                    {
                        // 评注库名
                        string strOldCommentDbName = DomUtil.GetAttr(nodeDatabase,
                            "commentDbName");

                        // 来自strDatabaseInfo
                        string strNewCommentDbName = DomUtil.GetAttr(nodeNewDatabase,
                            "commentDbName");
                        if (String.IsNullOrEmpty(strNewCommentDbName) == false
                            && strOldCommentDbName != strNewCommentDbName)
                        {
                            if (String.IsNullOrEmpty(strOldCommentDbName) == true
                                && String.IsNullOrEmpty(strNewCommentDbName) == false)
                            {
                                strError = "要创建评注库 '" + strNewCommentDbName + "',请使用create功能,而不能使用change功能";
                                goto ERROR1;
                            }

                            nRet = ChangeDbName(
                                channel,
                                strOldCommentDbName,
                                strNewCommentDbName,
                                () =>
                                {
                                    DomUtil.SetAttr(nodeDatabase, "commentDbName", strNewCommentDbName);
                                    bDbNameChanged = true;
                                    this.Changed = true;
                                },
                                out strError);
                            if (nRet == -1)
                                goto ERROR1;

#if NO
                            bDbNameChanged = true;

                            DomUtil.SetAttr(nodeDatabase, "commentDbName", strNewCommentDbName);
                            this.Changed = true;
#endif
                        }
                    }

                    // 是否参与流通
                    if (DomUtil.HasAttr(nodeNewDatabase, "inCirculation") == true)
                    {
                        string strOldInCirculation = DomUtil.GetAttr(nodeDatabase,
                            "inCirculation");
                        if (String.IsNullOrEmpty(strOldInCirculation) == true)
                            strOldInCirculation = "true";

                        string strNewInCirculation = DomUtil.GetAttr(nodeNewDatabase,
                            "inCirculation");
                        if (String.IsNullOrEmpty(strNewInCirculation) == true)
                            strNewInCirculation = "true";

                        if (strOldInCirculation != strNewInCirculation)
                        {
                            DomUtil.SetAttr(nodeDatabase, "inCirculation",
                                strNewInCirculation);
                            this.Changed = true;
                        }
                    }

                    // 角色
                    // TODO: 是否要进行检查?
                    if (DomUtil.HasAttr(nodeNewDatabase, "role") == true)
                    {
                        string strOldRole = DomUtil.GetAttr(nodeDatabase,
                            "role");

                        string strNewRole = DomUtil.GetAttr(nodeNewDatabase,
                            "role");

                        if (strOldRole != strNewRole)
                        {
                            DomUtil.SetAttr(nodeDatabase, "role",
                                strNewRole);
                            this.Changed = true;
                        }
                    }

                    // 2012/4/30
                    // 联合编目特性
                    if (DomUtil.HasAttr(nodeNewDatabase, "unionCatalogStyle") == true)
                    {
                        string strOldUnionCatalogStyle = DomUtil.GetAttr(nodeDatabase,
                            "unionCatalogStyle");

                        string strNewUnionCatalogStyle = DomUtil.GetAttr(nodeNewDatabase,
                            "unionCatalogStyle");

                        if (strOldUnionCatalogStyle != strNewUnionCatalogStyle)
                        {
                            DomUtil.SetAttr(nodeDatabase, "unionCatalogStyle",
                                strNewUnionCatalogStyle);
                            this.Changed = true;
                        }
                    }

                    // 复制
                    if (DomUtil.HasAttr(nodeNewDatabase, "replication") == true)
                    {
                        string strOldReplication = DomUtil.GetAttr(nodeDatabase,
                            "replication");

                        string strNewReplication = DomUtil.GetAttr(nodeNewDatabase,
                            "replication");

                        if (strOldReplication != strNewReplication)
                        {
                            DomUtil.SetAttr(nodeDatabase, "replication",
                                strNewReplication);
                            this.Changed = true;
                        }
                    }

                    // <itemdbgroup>内容更新,刷新配套的内存结构
                    nRet = this.LoadItemDbGroupParam(this.LibraryCfgDom,
                        out strError);
                    if (nRet == -1)
                    {
                        this.WriteErrorLog(strError);
                        return -1;
                    }

                    this.Changed = true;
                    continue;
                } // end of if 书目库名


                // 单独修改实体库名
                // 能修改是否参与流通
                if (this.IsItemDbName(strName) == true)
                {
                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@name='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的实体库(name属性)相关<database>元素没有找到";
                        return -1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许修改实体库定义";
                        return -1;
                    }

                    // 实体库名
                    string strOldEntityDbName = DomUtil.GetAttr(nodeDatabase,
                        "name");

                    // 来自strDatabaseInfo
                    string strNewEntityDbName = DomUtil.GetAttr(nodeNewDatabase,
                        "name");

                    if (strOldEntityDbName != strNewEntityDbName)
                    {
                        if (String.IsNullOrEmpty(strOldEntityDbName) == true
                            && String.IsNullOrEmpty(strNewEntityDbName) == false)
                        {
                            strError = "要创建实体库 '" + strNewEntityDbName + "',请使用create功能,而不能使用change功能";
                            goto ERROR1;
                        }

                        if (String.IsNullOrEmpty(strOldEntityDbName) == false
                            && String.IsNullOrEmpty(strNewEntityDbName) == true)
                        {
                            strError = "要删除实体库 '" + strNewEntityDbName + "',请使用delete功能,而不能使用change功能";
                            goto ERROR1;
                        }

                        nRet = ChangeDbName(
                            channel,
                            strOldEntityDbName,
                            strNewEntityDbName,
                                () =>
                                {
                                    DomUtil.SetAttr(nodeDatabase, "name", strNewEntityDbName);
                                    bDbNameChanged = true;
                                    this.Changed = true;
                                },
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;

#if NO
                        bDbNameChanged = true;

                        DomUtil.SetAttr(nodeDatabase, "name", strNewEntityDbName);
                        this.Changed = true;
#endif
                    }

                    // 是否参与流通
                    {
                        string strOldInCirculation = DomUtil.GetAttr(nodeDatabase,
                            "inCirculation");
                        if (String.IsNullOrEmpty(strOldInCirculation) == true)
                            strOldInCirculation = "true";

                        string strNewInCirculation = DomUtil.GetAttr(nodeNewDatabase,
                            "inCirculation");
                        if (String.IsNullOrEmpty(strNewInCirculation) == true)
                            strNewInCirculation = "true";

                        if (strOldInCirculation != strNewInCirculation)
                        {
                            DomUtil.SetAttr(nodeDatabase, "inCirculation",
                                strNewInCirculation);
                            this.Changed = true;
                        }

                    }

                    // <itemdbgroup>内容更新,刷新配套的内存结构
                    nRet = this.LoadItemDbGroupParam(this.LibraryCfgDom,
                        out strError);
                    if (nRet == -1)
                    {
                        this.WriteErrorLog(strError);
                        return -1;
                    }

                    this.Changed = true;
                    continue;
                }

                // 单独修改订购库名
                if (this.IsOrderDbName(strName) == true)
                {
                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@orderDbName='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的订购库(orderDbName属性)相关<database>元素没有找到";
                        return -1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许修改订购库定义";
                        return -1;
                    }

                    // 来自LibraryCfgDom
                    string strOldOrderDbName = DomUtil.GetAttr(nodeDatabase,
                        "orderDbName");

                    // 来自strDatabaseInfo
                    string strNewOrderDbName = DomUtil.GetAttr(nodeNewDatabase,
                        "name");

                    if (strOldOrderDbName != strNewOrderDbName)
                    {
                        if (String.IsNullOrEmpty(strOldOrderDbName) == true
                            && String.IsNullOrEmpty(strNewOrderDbName) == false)
                        {
                            strError = "要创建订购库 '" + strNewOrderDbName + "',请使用create功能,而不能使用change功能";
                            goto ERROR1;
                        }

                        if (String.IsNullOrEmpty(strOldOrderDbName) == false
                            && String.IsNullOrEmpty(strNewOrderDbName) == true)
                        {
                            strError = "要删除订购库 '" + strNewOrderDbName + "',请使用delete功能,而不能使用change功能";
                            goto ERROR1;
                        }

                        nRet = ChangeDbName(
                            channel,
                            strOldOrderDbName,
                            strNewOrderDbName,
                                () =>
                                {
                                    DomUtil.SetAttr(nodeDatabase, "orderDbName", strNewOrderDbName);
                                    bDbNameChanged = true;
                                    this.Changed = true;
                                },
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;

#if NO
                        bDbNameChanged = true;

                        DomUtil.SetAttr(nodeDatabase, "orderDbName", strNewOrderDbName);
                        this.Changed = true;
#endif
                    }

                    // <itemdbgroup>内容更新,刷新配套的内存结构
                    nRet = this.LoadItemDbGroupParam(this.LibraryCfgDom,
                        out strError);
                    if (nRet == -1)
                    {
                        this.WriteErrorLog(strError);
                        return -1;
                    }

                    this.Changed = true;
                    continue;
                }

                // 单独修改期库名
                if (this.IsIssueDbName(strName) == true)
                {
                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@issueDbName='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的期库(issueDbName属性)相关<database>元素没有找到";
                        return -1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许修改期库定义";
                        return -1;
                    }

                    // 来自LibraryCfgDom
                    string strOldIssueDbName = DomUtil.GetAttr(nodeDatabase,
                        "issueDbName");
                    // 来自strDatabaseInfo
                    string strNewIssueDbName = DomUtil.GetAttr(nodeNewDatabase,
                        "name");    // 2012/4/30 changed

                    if (strOldIssueDbName != strNewIssueDbName)
                    {
                        if (String.IsNullOrEmpty(strOldIssueDbName) == true
                            && String.IsNullOrEmpty(strNewIssueDbName) == false)
                        {
                            strError = "要创建期库 '" + strNewIssueDbName + "',请使用create功能,而不能使用change功能";
                            goto ERROR1;
                        }

                        if (String.IsNullOrEmpty(strOldIssueDbName) == false
                            && String.IsNullOrEmpty(strNewIssueDbName) == true)
                        {
                            strError = "要删除期库 '" + strNewIssueDbName + "',请使用delete功能,而不能使用change功能";
                            goto ERROR1;
                        }

                        nRet = ChangeDbName(
                            channel,
                            strOldIssueDbName,
                            strNewIssueDbName,
                                () =>
                                {
                                    DomUtil.SetAttr(nodeDatabase, "issueDbName", strNewIssueDbName);
                                    bDbNameChanged = true;
                                    this.Changed = true;
                                },
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;

#if NO
                        bDbNameChanged = true;

                        DomUtil.SetAttr(nodeDatabase, "issueDbName", strNewIssueDbName);
                        this.Changed = true;
#endif
                    }

                    // <itemdbgroup>内容更新,刷新配套的内存结构
                    nRet = this.LoadItemDbGroupParam(this.LibraryCfgDom,
                        out strError);
                    if (nRet == -1)
                    {
                        this.WriteErrorLog(strError);
                        return -1;
                    }

                    this.Changed = true;
                    continue;
                }

                // 单独修改评注库名
                if (this.IsCommentDbName(strName) == true)
                {
                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@commentDbName='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的评注库(commentDbName属性)相关<database>元素没有找到";
                        return -1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许修改评注库定义";
                        return -1;
                    }

                    // 来自LibraryCfgDom
                    string strOldCommentDbName = DomUtil.GetAttr(nodeDatabase,
                        "commentDbName");
                    // 来自strDatabaseInfo
                    string strNewCommentDbName = DomUtil.GetAttr(nodeNewDatabase,
                        "name");    // 2012/4/30 changed

                    if (strOldCommentDbName != strNewCommentDbName)
                    {
                        if (String.IsNullOrEmpty(strOldCommentDbName) == true
                            && String.IsNullOrEmpty(strNewCommentDbName) == false)
                        {
                            strError = "要创建评注库 '" + strNewCommentDbName + "',请使用create功能,而不能使用change功能";
                            goto ERROR1;
                        }

                        if (String.IsNullOrEmpty(strOldCommentDbName) == false
                            && String.IsNullOrEmpty(strNewCommentDbName) == true)
                        {
                            strError = "要删除评注库 '" + strNewCommentDbName + "',请使用delete功能,而不能使用change功能";
                            goto ERROR1;
                        }

                        nRet = ChangeDbName(
                            channel,
                            strOldCommentDbName,
                            strNewCommentDbName,
                                () =>
                                {
                                    DomUtil.SetAttr(nodeDatabase, "commentDbName", strNewCommentDbName);
                                    bDbNameChanged = true;
                                    this.Changed = true;
                                },
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;

#if NO
                        bDbNameChanged = true;

                        DomUtil.SetAttr(nodeDatabase, "commentDbName", strNewCommentDbName);
                        this.Changed = true;
#endif
                    }

                    // <itemdbgroup>内容更新,刷新配套的内存结构
                    nRet = this.LoadItemDbGroupParam(this.LibraryCfgDom,
                        out strError);
                    if (nRet == -1)
                    {
                        this.WriteErrorLog(strError);
                        return -1;
                    }

                    this.Changed = true;
                    continue;
                }

                // 修改读者库名
                if (this.IsReaderDbName(strName) == true)
                {
                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("readerdbgroup/database[@name='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的读者库(name属性)相关<database>元素没有找到";
                        return -1;
                    }

                    // 2012/9/9
                    // 分馆用户只允许修改属于管辖分馆的读者库
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        string strExistLibraryCode = DomUtil.GetAttr(nodeDatabase, "libraryCode");

                        if (string.IsNullOrEmpty(strExistLibraryCode) == true
                            || StringUtil.IsInList(strExistLibraryCode, strLibraryCodeList) == false)
                        {
                            strError = "修改读者库 '" + strName + "' 定义被拒绝。当前用户只能修改图书馆代码完全属于 '" + strLibraryCodeList + "' 范围的读者库";
                            return -1;
                        }
                    }

                    // 来自LibraryCfgDom
                    string strOldReaderDbName = DomUtil.GetAttr(nodeDatabase,
                        "name");
                    // 来自strDatabaseInfo
                    string strNewReaderDbName = DomUtil.GetAttr(nodeNewDatabase,
                        "name");

                    if (strOldReaderDbName != strNewReaderDbName)
                    {
                        if (String.IsNullOrEmpty(strOldReaderDbName) == true
                            && String.IsNullOrEmpty(strNewReaderDbName) == false)
                        {
                            strError = "要创建读者库 '" + strNewReaderDbName + "',请使用create功能,而不能使用change功能";
                            goto ERROR1;
                        }

                        if (String.IsNullOrEmpty(strOldReaderDbName) == false
                            && String.IsNullOrEmpty(strNewReaderDbName) == true)
                        {
                            strError = "要删除读者库 '" + strNewReaderDbName + "',请使用delete功能,而不能使用change功能";
                            goto ERROR1;
                        }

                        nRet = ChangeDbName(
                            channel,
                            strOldReaderDbName,
                            strNewReaderDbName,
                                () =>
                                {
                                    DomUtil.SetAttr(nodeDatabase, "name", strNewReaderDbName);
                                    bDbNameChanged = true;
                                    this.Changed = true;
                                },
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;

#if NO
                        bDbNameChanged = true;

                        DomUtil.SetAttr(nodeDatabase, "name", strNewReaderDbName);
                        this.Changed = true;
#endif
                    }

                    // 是否参与流通
                    // 只有当提交的 XML 片断中具有 inCirculation 属性的时候,才会发生修改
                    if (nodeNewDatabase.GetAttributeNode("inCirculation") != null)
                    {
                        // 来自LibraryCfgDom
                        string strOldInCirculation = DomUtil.GetAttr(nodeDatabase,
                            "inCirculation");
                        if (String.IsNullOrEmpty(strOldInCirculation) == true)
                            strOldInCirculation = "true";

                        // 来自strDatabaseInfo
                        string strNewInCirculation = DomUtil.GetAttr(nodeNewDatabase,
                            "inCirculation");
                        if (String.IsNullOrEmpty(strNewInCirculation) == true)
                            strNewInCirculation = "true";

                        if (strOldInCirculation != strNewInCirculation)
                        {
                            DomUtil.SetAttr(nodeDatabase,
                                "inCirculation",
                                strNewInCirculation);
                            this.Changed = true;
                        }

                    }

                    // 2012/9/7
                    // 图书馆代码
                    // 只有当提交的 XML 片断中具有 libraryCode 属性的时候,才会发生修改
                    if (nodeNewDatabase.GetAttributeNode("libraryCode") != null)
                    {
                        // 来自LibraryCfgDom
                        string strOldLibraryCode = DomUtil.GetAttr(nodeDatabase,
                            "libraryCode");
                        // 来自strDatabaseInfo
                        string strNewLibraryCode = DomUtil.GetAttr(nodeNewDatabase,
                            "libraryCode");

                        if (strOldLibraryCode != strNewLibraryCode)
                        {
                            if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                            {
                                if (string.IsNullOrEmpty(strNewLibraryCode) == true
                                    || StringUtil.IsInList(strNewLibraryCode, strLibraryCodeList) == false)
                                {
                                    strError = "修改读者库 '" + strName + "' 定义被拒绝。修改后的新图书馆代码必须完全属于 '" + strLibraryCodeList + "' 范围";
                                    return -1;
                                }
                            }

                            // 检查一个单独的图书馆代码是否格式正确
                            // 要求不能为 '*',不能包含逗号
                            // return:
                            //      -1  校验函数本身出错了
                            //      0   校验正确
                            //      1   校验发现问题。strError中有描述
                            nRet = VerifySingleLibraryCode(strNewLibraryCode,
                out strError);
                            if (nRet != 0)
                            {
                                strError = "图书馆代码 '" + strNewLibraryCode + "' 格式错误: " + strError;
                                goto ERROR1;
                            }

                            DomUtil.SetAttr(nodeDatabase,
                                "libraryCode",
                                strNewLibraryCode);
                            this.Changed = true;
                        }
                    }

                    // <readerdbgroup>内容更新,刷新配套的内存结构
                    this.LoadReaderDbGroupParam(this.LibraryCfgDom);

                    this.Changed = true;
                    continue;
                }

                // 修改预约到书库名
                if (this.ArrivedDbName == strName)
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许修改预约到书库定义";
                        return -1;
                    }

                    string strOldArrivedDbName = this.ArrivedDbName;

                    // 来自strDatabaseInfo
                    string strNewArrivedDbName = DomUtil.GetAttr(nodeNewDatabase,
                        "name");

                    if (strOldArrivedDbName != strNewArrivedDbName)
                    {
                        if (String.IsNullOrEmpty(strOldArrivedDbName) == true
                            && String.IsNullOrEmpty(strNewArrivedDbName) == false)
                        {
                            strError = "要创建预约到书库 '" + strNewArrivedDbName + "',请使用create功能,而不能使用change功能";
                            goto ERROR1;
                        }

                        if (String.IsNullOrEmpty(strOldArrivedDbName) == false
                            && String.IsNullOrEmpty(strNewArrivedDbName) == true)
                        {
                            strError = "要删除预约到书库 '" + strNewArrivedDbName + "',请使用delete功能,而不能使用change功能";
                            goto ERROR1;
                        }

                        nRet = ChangeDbName(
                            channel,
                            strOldArrivedDbName,
                            strNewArrivedDbName,
                                () =>
                                {
                                    this.ArrivedDbName = strNewArrivedDbName;
                                    this.Changed = true;
                                },
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;

#if NO
                        this.Changed = true;
                        this.ArrivedDbName = strNewArrivedDbName;
#endif
                    }

                    continue;
                }

                // 修改违约金库名
                if (this.AmerceDbName == strName)
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许修改违约金库定义";
                        return -1;
                    }

                    string strOldAmerceDbName = this.AmerceDbName;

                    // 来自strDatabaseInfo
                    string strNewAmerceDbName = DomUtil.GetAttr(nodeNewDatabase,
                        "name");

                    if (strOldAmerceDbName != strNewAmerceDbName)
                    {
                        if (String.IsNullOrEmpty(strOldAmerceDbName) == true
                            && String.IsNullOrEmpty(strNewAmerceDbName) == false)
                        {
                            strError = "要创建违约金库 '" + strNewAmerceDbName + "',请使用create功能,而不能使用change功能";
                            goto ERROR1;
                        }

                        if (String.IsNullOrEmpty(strOldAmerceDbName) == false
                            && String.IsNullOrEmpty(strNewAmerceDbName) == true)
                        {
                            strError = "要删除违约金库 '" + strNewAmerceDbName + "',请使用delete功能,而不能使用change功能";
                            goto ERROR1;
                        }

                        nRet = ChangeDbName(
                            channel,
                            strOldAmerceDbName,
                            strNewAmerceDbName,
                                () =>
                                {
                                    this.AmerceDbName = strNewAmerceDbName;
                                    this.Changed = true;
                                },
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;

#if NO
                        this.Changed = true;
                        this.AmerceDbName = strNewAmerceDbName;
#endif
                    }

                    continue;
                }

                // 修改发票库名
                if (this.InvoiceDbName == strName)
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许修改发票库定义";
                        return -1;
                    }

                    string strOldInvoiceDbName = this.InvoiceDbName;

                    // 来自strDatabaseInfo
                    string strNewInvoiceDbName = DomUtil.GetAttr(nodeNewDatabase,
                        "name");

                    if (strOldInvoiceDbName != strNewInvoiceDbName)
                    {
                        if (String.IsNullOrEmpty(strOldInvoiceDbName) == true
                            && String.IsNullOrEmpty(strNewInvoiceDbName) == false)
                        {
                            strError = "要创建发票库 '" + strNewInvoiceDbName + "',请使用create功能,而不能使用change功能";
                            goto ERROR1;
                        }

                        if (String.IsNullOrEmpty(strOldInvoiceDbName) == false
                            && String.IsNullOrEmpty(strNewInvoiceDbName) == true)
                        {
                            strError = "要删除发票库 '" + strNewInvoiceDbName + "',请使用delete功能,而不能使用change功能";
                            goto ERROR1;
                        }

                        nRet = ChangeDbName(
                            channel,
                            strOldInvoiceDbName,
                            strNewInvoiceDbName,
                                () =>
                                {
                                    this.InvoiceDbName = strNewInvoiceDbName;
                                    this.Changed = true;
                                },
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;

#if NO
                        this.Changed = true;
                        this.InvoiceDbName = strNewInvoiceDbName;
#endif
                    }

                    continue;
                }


                // 修改消息库名
                if (this.MessageDbName == strName)
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许修改预约消息库定义";
                        return -1;
                    }

                    string strOldMessageDbName = this.MessageDbName;

                    // 来自strDatabaseInfo
                    string strNewMessageDbName = DomUtil.GetAttr(nodeNewDatabase,
                        "name");

                    if (strOldMessageDbName != strNewMessageDbName)
                    {
                        if (String.IsNullOrEmpty(strOldMessageDbName) == true
                            && String.IsNullOrEmpty(strNewMessageDbName) == false)
                        {
                            strError = "要创建消息库 '" + strNewMessageDbName + "',请使用create功能,而不能使用change功能";
                            goto ERROR1;
                        }

                        if (String.IsNullOrEmpty(strOldMessageDbName) == false
                            && String.IsNullOrEmpty(strNewMessageDbName) == true)
                        {
                            strError = "要删除消息库 '" + strNewMessageDbName + "',请使用delete功能,而不能使用change功能";
                            goto ERROR1;
                        }

                        nRet = ChangeDbName(
                            channel,
                            strOldMessageDbName,
                            strNewMessageDbName,
                                () =>
                                {
                                    this.MessageDbName = strNewMessageDbName;
                                    this.Changed = true;
                                },
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;

#if NO
                        this.Changed = true;
                        this.MessageDbName = strNewMessageDbName;
#endif
                    }

                    continue;
                }

                // 修改实用库名
                if (IsUtilDbName(strName) == true)
                {
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("utilDb/database[@name='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "不存在name属性值为 '"+strName+"' 的<utilDb/database>的元素";
                        goto ERROR1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许修改实用库定义";
                        return -1;
                    }

                    string strOldUtilDbName = strName;

                    // 来自strDatabaseInfo
                    string strNewUtilDbName = DomUtil.GetAttr(nodeNewDatabase,
                        "name");

                    if (strOldUtilDbName != strNewUtilDbName)
                    {
                        if (String.IsNullOrEmpty(strOldUtilDbName) == true
                            && String.IsNullOrEmpty(strNewUtilDbName) == false)
                        {
                            strError = "要创建实用库 '" + strNewUtilDbName + "',请使用create功能,而不能使用change功能";
                            goto ERROR1;
                        }

                        if (String.IsNullOrEmpty(strOldUtilDbName) == false
                            && String.IsNullOrEmpty(strNewUtilDbName) == true)
                        {
                            strError = "要删除实用库 '" + strNewUtilDbName + "',请使用delete功能,而不能使用change功能";
                            goto ERROR1;
                        }

                        nRet = ChangeDbName(
                            channel,
                            strOldUtilDbName,
                            strNewUtilDbName,
                                () =>
                                {
                                    DomUtil.SetAttr(nodeDatabase, "name", strNewUtilDbName);
                                    this.Changed = true;
                                },
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;

#if NO
                        this.Changed = true;
                        DomUtil.SetAttr(nodeDatabase, "name", strNewUtilDbName);
#endif
                    }

                    string strOldType = DomUtil.GetAttr(nodeDatabase, "type");
                    string strNewType = DomUtil.GetAttr(nodeNewDatabase, "type");

                    if (strOldType != strNewType)
                    {
                        DomUtil.SetAttr(nodeDatabase, "type", strNewType);
                        this.Changed = true;
                        // TODO: 类型修改后,是否要应用新的模板来修改数据库定义?这是个大问题
                    }

                    continue;
                }

                strError = "数据库名 '" + strName + "' 不属于 dp2library 目前管辖的范围...";
                return -1;
            }

            if (this.Changed == true)
                this.ActivateManagerThread();

            if (bDbNameChanged == true)
            {
                nRet = InitialKdbs(
                    Channels,
                    out strError);
                if (nRet == -1)
                    return -1;
                // 重新初始化虚拟库定义
                this.vdbs = null;
                nRet = this.InitialVdbs(Channels,
                    out strError);
                if (nRet == -1)
                    return -1;
            }

            return 0;
        ERROR1:
            // 2015/1/29
            if (this.Changed == true)
                this.ActivateManagerThread();

            // 2015/1/29
            if (bDbNameChanged == true)
            {
                {
                    string strError1 = "";
                    nRet = InitialKdbs(
                        Channels,
                        out strError1);
                    if (nRet == -1)
                        strError += "; 在收尾的时候进行 InitialKdbs() 调用又出错:" + strError1;
                }

                {
                    string strError1 = "";
                    // 重新初始化虚拟库定义
                    this.vdbs = null;
                    nRet = this.InitialVdbs(Channels,
                        out strError1);
                    if (nRet == -1)
                        strError += "; 在收尾的时候进行 InitialVdbs() 调用又出错:" + strError1;
                }
            }
            return -1;
        }
예제 #4
0
        // 删除数据库
        int DeleteDatabase(
            RmsChannelCollection Channels,
            string strLibraryCodeList,
            string strDatabaseNames,
            out string strOutputInfo,
            out string strError)
        {
            strOutputInfo = "";
            strError = "";

            int nRet = 0;
            // long lRet = 0;

            bool bDbNameChanged = false;

            RmsChannel channel = Channels.GetChannel(this.WsUrl);

            string[] names = strDatabaseNames.Split(new char[] { ',' });
            for (int i = 0; i < names.Length; i++)
            {
                string strName = names[i].Trim();
                if (String.IsNullOrEmpty(strName) == true)
                    continue;

                // 书目库整体删除,也是可以的
                // TODO: 将来可以考虑单独删除书目库而不删除组内相关库
                if (this.IsBiblioDbName(strName) == true)
                {
                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@biblioDbName='"+strName+"']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的书目库(biblioDbName属性)相关<database>元素没有找到";
                        return -1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许删除书目库";
                        return -1;
                    }

                    // 删除书目库
                    /*
                    lRet = channel.DoDeleteDB(strName, out strError);
                    if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                    {
                        strError = "删除书目库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }
                     * */
                    nRet = DeleteDatabase(channel, strName, out strError);
                    if (nRet == -1)
                    {
                        strError = "删除书目库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }

                    bDbNameChanged = true;

                    // 删除实体库
                    string strEntityDbName = DomUtil.GetAttr(nodeDatabase, "name");
                    if (String.IsNullOrEmpty(strEntityDbName) == false)
                    {
                        /*
                        lRet = channel.DoDeleteDB(strEntityDbName, out strError);
                        if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                        {
                            strError = "删除书目库 '" + strName + "' 所从属的实体库 '" + strEntityDbName + "' 时发生错误: " + strError;
                            return -1;
                        }
                         * */
                        nRet = DeleteDatabase(channel, strEntityDbName, out strError);
                        if (nRet == -1)
                        {
                            strError = "删除书目库 '" + strName + "' 所从属的实体库 '" + strEntityDbName + "' 时发生错误: " + strError;
                            return -1;
                        }
                    }

                    // 删除订购库
                    string strOrderDbName = DomUtil.GetAttr(nodeDatabase, "orderDbName");
                    if (String.IsNullOrEmpty(strOrderDbName) == false)
                    {
                        /*
                        lRet = channel.DoDeleteDB(strOrderDbName, out strError);
                        if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                        {
                            strError = "删除书目库 '" + strName + "' 所从属的订购库 '" + strOrderDbName + "' 时发生错误: " + strError;
                            return -1;
                        }
                         * */
                        nRet = DeleteDatabase(channel, strOrderDbName, out strError);
                        if (nRet == -1)
                        {
                            strError = "删除书目库 '" + strName + "' 所从属的订购库 '" + strOrderDbName + "' 时发生错误: " + strError;
                            return -1;
                        }

                    }

                    // 删除期库
                    string strIssueDbName = DomUtil.GetAttr(nodeDatabase, "issueDbName");
                    if (String.IsNullOrEmpty(strIssueDbName) == false)
                    {
                        /*
                        lRet = channel.DoDeleteDB(strIssueDbName, out strError);
                        if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                        {
                            strError = "删除书目库 '" + strName + "' 所从属的期库 '" + strIssueDbName + "' 时发生错误: " + strError;
                            return -1;
                        }
                         * */
                        nRet = DeleteDatabase(channel, strIssueDbName, out strError);
                        if (nRet == -1)
                        {
                            strError = "删除书目库 '" + strName + "' 所从属的期库 '" + strIssueDbName + "' 时发生错误: " + strError;
                            return -1;
                        }
                    }

                    // 删除评注库
                    string strCommentDbName = DomUtil.GetAttr(nodeDatabase, "commentDbName");
                    if (String.IsNullOrEmpty(strCommentDbName) == false)
                    {
                        nRet = DeleteDatabase(channel, strCommentDbName, out strError);
                        if (nRet == -1)
                        {
                            strError = "删除书目库 '" + strName + "' 所从属的评注库 '" + strCommentDbName + "' 时发生错误: " + strError;
                            return -1;
                        }
                    }

                    nodeDatabase.ParentNode.RemoveChild(nodeDatabase);

                    // <itemdbgroup>内容更新,刷新配套的内存结构
                    nRet = this.LoadItemDbGroupParam(this.LibraryCfgDom,
                        out strError);
                    if (nRet == -1)
                    {
                        this.WriteErrorLog(strError);
                        return -1;
                    }

                    /*
                    // 删除一个数据库在OPAC可检索库中的定义
                    // return:
                    //      -1  error
                    //      0   not change
                    //      1   changed
                    nRet = RemoveOpacDatabaseDef(
                        Channels,
                        strName,
                        out strError);
                    if (nRet == -1)
                    {
                        this.Changed = true;
                        this.ActivateMangerThread();
                        return -1;
                    }*/

                    this.Changed = true;
                    this.ActivateManagerThread();

                    continue;
                }

                // 单独删除实体库
                if (this.IsItemDbName(strName) == true)
                {
                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@name='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的实体库(name属性)相关<database>元素没有找到";
                        return -1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许删除实体库";
                        return -1;
                    }

                    // 删除实体库
                    /*
                    lRet = channel.DoDeleteDB(strName, out strError);
                    if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                    {
                        strError = "删除实体库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }
                     * */
                    nRet = DeleteDatabase(channel, strName, out strError);
                    if (nRet == -1)
                    {
                        strError = "删除实体库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }

                    bDbNameChanged = true;

                    DomUtil.SetAttr(nodeDatabase, "name", null);

                    // <itemdbgroup>内容更新,刷新配套的内存结构
                    nRet = this.LoadItemDbGroupParam(this.LibraryCfgDom,
                        out strError);
                    if (nRet == -1)
                    {
                        this.WriteErrorLog(strError);
                        return -1;
                    }

                    this.Changed = true;
                    this.ActivateManagerThread();
                    continue;
                }

                // 单独删除订购库
                if (this.IsOrderDbName(strName) == true)
                {
                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@orderDbName='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的订购库(orderDbName属性)相关<database>元素没有找到";
                        return -1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许删除订购库";
                        return -1;
                    }

                    // 删除订购库
                    /*
                    lRet = channel.DoDeleteDB(strName, out strError);
                    if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                    {
                        strError = "删除订购库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }
                     * */
                    nRet = DeleteDatabase(channel, strName, out strError);
                    if (nRet == -1)
                    {
                        strError = "删除订购库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }


                    bDbNameChanged = true;

                    DomUtil.SetAttr(nodeDatabase, "orderDbName", null);

                    // <itemdbgroup>内容更新,刷新配套的内存结构
                    nRet = this.LoadItemDbGroupParam(this.LibraryCfgDom,
                        out strError);
                    if (nRet == -1)
                    {
                        this.WriteErrorLog(strError);
                        return -1;
                    }

                    this.Changed = true;
                    this.ActivateManagerThread();
                    continue;
                }

                // 单独删除期库
                if (this.IsIssueDbName(strName) == true)
                {
                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@issueDbName='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的期库(issueDbName属性)相关<database>元素没有找到";
                        return -1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许删除期库";
                        return -1;
                    }

                    // 删除期库
                    /*
                    lRet = channel.DoDeleteDB(strName, out strError);
                    if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                    {
                        strError = "删除期库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }
                     * */
                    nRet = DeleteDatabase(channel, strName, out strError);
                    if (nRet == -1)
                    {
                        strError = "删除期库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }

                    bDbNameChanged = true;

                    DomUtil.SetAttr(nodeDatabase, "issueDbName", null);

                    // <itemdbgroup>内容更新,刷新配套的内存结构
                    nRet = this.LoadItemDbGroupParam(this.LibraryCfgDom,
                        out strError);
                    if (nRet == -1)
                    {
                        this.WriteErrorLog(strError);
                        return -1;
                    }

                    this.Changed = true;
                    this.ActivateManagerThread();
                    continue;
                }

                // 单独删除评注库
                if (this.IsCommentDbName(strName) == true)
                {
                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@commentDbName='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的评注库(commentDbName属性)相关<database>元素没有找到";
                        return -1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许删除评注库";
                        return -1;
                    }

                    nRet = DeleteDatabase(channel, strName, out strError);
                    if (nRet == -1)
                    {
                        strError = "删除评注库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }

                    bDbNameChanged = true;

                    DomUtil.SetAttr(nodeDatabase, "commentDbName", null);

                    // <itemdbgroup>内容更新,刷新配套的内存结构
                    nRet = this.LoadItemDbGroupParam(this.LibraryCfgDom,
                        out strError);
                    if (nRet == -1)
                    {
                        this.WriteErrorLog(strError);
                        return -1;
                    }

                    this.Changed = true;
                    this.ActivateManagerThread();
                    continue;
                }

                // 删除读者库
                if (this.IsReaderDbName(strName) == true)
                {
                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("readerdbgroup/database[@name='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的读者库(name属性)相关<database>元素没有找到";
                        return -1;
                    }


                    // 2012/9/9
                    // 分馆用户只允许删除属于管辖分馆的读者库
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        string strExistLibraryCode = DomUtil.GetAttr(nodeDatabase, "libraryCode");

                        if (string.IsNullOrEmpty(strExistLibraryCode) == true
                            || StringUtil.IsInList(strExistLibraryCode, strLibraryCodeList) == false)
                        {
                            strError = "删除读者库 '" + strName + "' 被拒绝。当前用户只能删除图书馆代码完全完全属于 '" + strLibraryCodeList + "' 范围的读者库";
                            return -1;
                        }
                    }

                    // 删除读者库
                    /*
                    lRet = channel.DoDeleteDB(strName, out strError);
                    if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                    {
                        strError = "删除读者库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }
                     * */
                    nRet = DeleteDatabase(channel, strName, out strError);
                    if (nRet == -1)
                    {
                        strError = "删除读者库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }

                    bDbNameChanged = true;

                    nodeDatabase.ParentNode.RemoveChild(nodeDatabase);

                    // <readerdbgroup>内容更新,刷新配套的内存结构
                    this.LoadReaderDbGroupParam(this.LibraryCfgDom);

                    /*
                    // 删除一个数据库在OPAC可检索库中的定义
                    // return:
                    //      -1  error
                    //      0   not change
                    //      1   changed
                    nRet = RemoveOpacDatabaseDef(
                        Channels,
                        strName,
                        out strError);
                    if (nRet == -1)
                    {
                        this.Changed = true;
                        this.ActivateMangerThread();
                        return -1;
                    }
                     * */

                    this.Changed = true;
                    this.ActivateManagerThread();
                    continue;
                }

                // 删除预约到书库
                if (this.ArrivedDbName == strName)
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许删除预约到书库";
                        return -1;
                    }

                    // 删除预约到书库
                    /*
                    lRet = channel.DoDeleteDB(strName, out strError);
                    if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                    {
                        strError = "删除预约到书库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }
                     * */
                    nRet = DeleteDatabase(channel, strName, out strError);
                    if (nRet == -1)
                    {
                        strError = "删除预约到书库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }

                    this.ArrivedDbName = "";

                    /*
                    // 删除一个数据库在OPAC可检索库中的定义
                    // return:
                    //      -1  error
                    //      0   not change
                    //      1   changed
                    nRet = RemoveOpacDatabaseDef(
                        Channels,
                        strName,
                        out strError);
                    if (nRet == -1)
                    {
                        this.Changed = true;
                        this.ActivateMangerThread();
                        return -1;
                    }
                     * */

                    this.Changed = true;
                    this.ActivateManagerThread();
                    continue;
                }

                // 删除违约金库
                if (this.AmerceDbName == strName)
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许删除违约金库";
                        return -1;
                    }

                    // 删除违约金库
                    /*
                    lRet = channel.DoDeleteDB(strName, out strError);
                    if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                    {
                        strError = "删除违约金库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }
                     * */
                    nRet = DeleteDatabase(channel, strName, out strError);
                    if (nRet == -1)
                    {
                        strError = "删除违约金库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }


                    this.AmerceDbName = "";

                    /*
                    // 删除一个数据库在OPAC可检索库中的定义
                    // return:
                    //      -1  error
                    //      0   not change
                    //      1   changed
                    nRet = RemoveOpacDatabaseDef(
                        Channels,
                        strName,
                        out strError);
                    if (nRet == -1)
                    {
                        this.Changed = true;
                        this.ActivateMangerThread();
                        return -1;
                    }*/

                    this.Changed = true;
                    this.ActivateManagerThread();
                    continue;
                }

                // 删除发票库
                if (this.InvoiceDbName == strName)
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许删除发票库";
                        return -1;
                    }

                    nRet = DeleteDatabase(channel, strName, out strError);
                    if (nRet == -1)
                    {
                        strError = "删除发票库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }

                    this.InvoiceDbName = "";

                    this.Changed = true;
                    this.ActivateManagerThread();
                    continue;
                }


                // 删除消息库
                if (this.MessageDbName == strName)
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许删除消息库";
                        return -1;
                    }

                    // 删除消息库
                    /*
                    lRet = channel.DoDeleteDB(strName, out strError);
                    if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                    {
                        strError = "删除消息库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }
                     * */
                    nRet = DeleteDatabase(channel, strName, out strError);
                    if (nRet == -1)
                    {
                        strError = "删除消息库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }

                    this.MessageDbName = "";

                    /*
                    // 删除一个数据库在OPAC可检索库中的定义
                    // return:
                    //      -1  error
                    //      0   not change
                    //      1   changed
                    nRet = RemoveOpacDatabaseDef(
                        Channels,
                        strName,
                        out strError);
                    if (nRet == -1)
                    {
                        this.Changed = true;
                        this.ActivateMangerThread();
                        return -1;
                    }
                     * */

                    this.Changed = true;
                    this.ActivateManagerThread();
                    continue;
                }

                // 单独删除实用库
                if (IsUtilDbName(strName) == true)
                {
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("utilDb/database[@name='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "不存在name属性值为 '" + strName + "' 的<utilDb/database>的元素";
                        return -1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许删除实用库";
                        return -1;
                    }

                    // 删除实用库
                    /*
                    lRet = channel.DoDeleteDB(strName, out strError);
                    if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                    {
                        strError = "删除实用库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }
                     * */
                    nRet = DeleteDatabase(channel, strName, out strError);
                    if (nRet == -1)
                    {
                        strError = "删除实用库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }

                    nodeDatabase.ParentNode.RemoveChild(nodeDatabase);

                    /*
                    // 删除一个数据库在OPAC可检索库中的定义
                    // return:
                    //      -1  error
                    //      0   not change
                    //      1   changed
                    nRet = RemoveOpacDatabaseDef(
                        Channels,
                        strName,
                        out strError);
                    if (nRet == -1)
                    {
                        this.Changed = true;
                        this.ActivateMangerThread();
                        return -1;
                    }
                     * */

                    this.Changed = true;
                    this.ActivateManagerThread();
                    continue;
                }

                strError = "数据库名 '" +strName+ "' 不属于 dp2library 目前管辖的范围...";
                return -1;
            }

            if (bDbNameChanged == true)
            {
                nRet = InitialKdbs(
                    Channels,
                    out strError);
                if (nRet == -1)
                    return -1;
                // 重新初始化虚拟库定义
                this.vdbs = null;
                nRet = this.InitialVdbs(Channels,
                    out strError);
                if (nRet == -1)
                    return -1;
            }

            return 0;
        }
예제 #5
0
        // 重设置代理帐户密码
        int ResetManageUserPassword(out string strError)
        {
            strError = "";
            if (this.textBox_kernelUrl.Text == "")
            {
                strError = "尚未指定dp2Kernel服务器URL";
                return -1;
            }

            if (this.textBox_manageUserName.Text == "")
            {
                strError = "尚未指定代理帐户的用户名";
                return -1;
            }

            if (this.textBox_managePassword.Text != this.textBox_confirmManagePassword.Text)
            {
                strError = "代理帐户 密码 和 再次输入密码 不一致。请重新输入。";
                return -1;
            }

            RmsChannelCollection channels = new RmsChannelCollection();

            channels.AskAccountInfo -= new AskAccountInfoEventHandle(channels_AskAccountInfo);
            channels.AskAccountInfo += new AskAccountInfoEventHandle(channels_AskAccountInfo);

            RmsChannel channel = channels.GetChannel(this.textBox_kernelUrl.Text);
            if (channel == null)
            {
                strError = "channel == null";
                return -1;
            }

            int nRet = channel.UiLogin("请用root用户身份登录,以便重设代理帐户密码。",
                "",
                LoginStyle.None,
                out strError);
            if (nRet == -1 || nRet == 0)
            {
                strError = "以root用户身份登录失败: " + strError;
                return -1;
            }

            // 获得用户库名


            string strRecPath = "";
            string strXml = "";
            byte[] baTimeStamp = null;


            // 查重,看这个用户名是否已经存在
            // 获得用户记录
            // return:
            //      -1  error
            //      0   not found
            //      >=1   检索命中的条数
            nRet = GetUserRecord(
                channel,
                this.textBox_manageUserName.Text,
                out strRecPath,
                out strXml,
                out baTimeStamp,
                out strError);
            if (nRet == -1)
            {
                strError = "获取用户 '" + this.textBox_manageUserName.Text + "' 信息时发生错误: " + strError;
                return -1;
            }

            if (nRet == 0)
            {
                strError = "用户 '" + this.textBox_manageUserName.Text + "' 尚不存在,因此无法重设其密码。请直接创建。";
                return -1;
            }

            if (nRet > 1)
            {
                strError = "以 '" + this.textBox_manageUserName.Text + "' 为用户名 的用户记录存在多条,这是一个严重错误,请利用root身份启用dp2manager尽快修正此错误。";
                return -1;
            }

            // 修改密码
            nRet = ResetUserRecordPassword(ref strXml,
                out strError);
            if (nRet == -1)
            {
                strError = "构造用户记录时发生错误: " + strError;
                return -1;
            }

            string strOutputPath = "";
            byte[] baOutputTimeStamp;

            if (strRecPath == "")
            {
                Debug.Assert(false, "不可能出现的情况。");
                strRecPath = Defs.DefaultUserDb.Name + "/" + "?";
            }

            long lRet = channel.DoSaveTextRes(
                strRecPath,
                strXml,
                false,	// bInlucdePreamble
                "",	// style
                baTimeStamp,	// baTimeStamp,
                out baOutputTimeStamp,
                out strOutputPath,
                out strError);
            if (lRet == -1)
            {
                strError = "保存用户记录时发生错误: " + strError;
                return -1;
            }

            channel.DoLogout(out strError);

            return 0;
        }
예제 #6
0
        private void CfgFileEditDlg_Load(object sender, System.EventArgs e)
        {
            button_export.Enabled = false;

            MemoryStream stream = null;
            string       strMetaData;
            string       strError = "";
            string       strMime  = "";

            Hashtable values = null;

            if (Obj != null)
            {
                if (this.Obj.Content != null)
                {
                    stream      = new MemoryStream(this.Obj.Content);
                    this.Stream = stream;
                    this.Stream.Seek(0, SeekOrigin.Begin);

                    button_export.Enabled = true;
                }

                this.TimeStamp = this.Obj.TimeStamp;

                strMetaData = this.Obj.Metadata;

                // 观察mime
                // 取metadata
                values = StringUtil.ParseMetaDataXml(strMetaData,
                                                     out strError);
                if (values == null)
                {
                    MessageBox.Show(this, strError);
                    return;
                }
                strMime = (string)values["mimetype"];
                if (strMime == null || strMime == "")
                {
                    strMime = "text";
                }
                this.Mime = strMime;

                this.LocalPath = (string)values["localpath"];
                if (this.LocalPath == null)
                {
                    this.LocalPath = "";
                }

                this.textBox_content.Text = "";

                // string strFirstPart = StringUtil.GetFirstPartPath(ref strMime);
                if (this.IsText == true)
                {
                    if (this.Stream != null)
                    {
                        this.Stream.Seek(0, SeekOrigin.Begin);
                        using (StreamReader sr = new StreamReader(this.Stream, Encoding.UTF8))
                        {
                            this.textBox_content.Text = ConvertCrLf(sr.ReadToEnd());
                        }
                    }
                }
                else
                {
                }

                //////

                button_OK.Enabled = false;

                this.textBox_content.SelectionStart  = 0;
                this.textBox_content.SelectionLength = 0;
                return;
            }

            this.channel = Channels.GetChannel(this.ServerUrl);
            Debug.Assert(channel != null, "Channels.GetChannel() 异常");

            DigitalPlatform.Stop stop = null;

            if (stopManager != null)
            {
                stop = new DigitalPlatform.Stop();

                stop.Register(this.stopManager, true);  // 和容器关联

                stop.OnStop += new StopEventHandler(this.DoStop);
                stop.Initial("正在下载配置文件: " + this.Path);

                stop.BeginLoop();
            }

            // string strContent = "";
            byte[] baTimeStamp = null;
            string strOutputPath;

            string strStyle = "content,data,metadata,timestamp,outputpath";

            //			string strStyle = "attachment,data,metadata,timestamp,outputpath";

            stream = new MemoryStream();

            long lRet = channel.GetRes(
                this.Path,
                stream,
                stop,   // stop,
                strStyle,
                null,   // byte [] input_timestamp,
                out strMetaData,
                out baTimeStamp,
                out strOutputPath,
                out strError);

            /*
             * long lRet = channel.GetRes((
             *  this.Path,
             *  out strContent,
             *  out strMetaData,
             *  out baTimeStamp,
             *  out strOutputPath,
             *  out strError);
             */

            if (stopManager != null)
            {
                stop.EndLoop();
                stop.OnStop -= new StopEventHandler(this.DoStop);
                stop.Initial("");
            }

            if (lRet == -1)
            {
                MessageBox.Show(this, strError);
                goto FINISH;
            }

            this.Stream = stream;
            this.Stream.Seek(0, SeekOrigin.Begin);

            button_export.Enabled = true;


            this.TimeStamp = baTimeStamp;

            // 观察mime
            // 取metadata
            values = StringUtil.ParseMetaDataXml(strMetaData,
                                                 out strError);
            if (values == null)
            {
                MessageBox.Show(this, strError);
                goto FINISH;
            }
            strMime = (string)values["mimetype"];
            if (strMime == null || strMime == "")
            {
                strMime = "text";
            }
            this.Mime = strMime;

            this.LocalPath = (string)values["localpath"];
            if (this.LocalPath == null)
            {
                this.LocalPath = "";
            }

            // string strFirstPart = StringUtil.GetFirstPartPath(ref strMime);
            if (this.IsText == true)
            {
                this.Stream.Seek(0, SeekOrigin.Begin);
                using (StreamReader sr = new StreamReader(this.Stream, Encoding.UTF8))
                {
                    this.textBox_content.Text = ConvertCrLf(sr.ReadToEnd());
                }
                // 注意,此后 this.Stream 被关闭
            }
            else
            {
                //this.textBox_content.Text = "<二进制内容无法直接编辑>";
                //this.textBox_content.ReadOnly = true;
                //this.button_format.Enabled = false;
            }

            //////

            button_OK.Enabled = false;
FINISH:
            if (stopManager != null && stop != null)
            {
                stop.Unregister();      // 和容器关联
                stop = null;
            }

            this.channel = null;

            this.textBox_content.SelectionStart  = 0;
            this.textBox_content.SelectionLength = 0;
        }
예제 #7
0
        /*
<root>
  <operation>repairBorrowInfo</operation> 
  <action>...</action> 具体动作 有 repairreaderside repairitemside
  <readerBarcode>...</readerBarcode>
  <itemBarcode>...</itemBarcode>
  <confirmItemRecPath>...</confirmItemRecPath> 辅助判断用的册记录路径
  <operator>test</operator> 
  <operTime>Fri, 08 Dec 2006 10:12:20 GMT</operTime> 
</root>
         * * 
         * */
        public int RecoverRepairBorrowInfo(
    RmsChannelCollection Channels,
    RecoverLevel level,
    XmlDocument domLog,
    Stream attachmentLog,
    out string strError)
        {
            strError = "";
            int nRet = 0;

            // 暂时把Robust当作Logic处理
            if (level == RecoverLevel.Robust)
                level = RecoverLevel.Logic;

            long lRet = 0;
            // int nRet = 0;

            RmsChannel channel = Channels.GetChannel(this.WsUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }

            bool bReuse = false;    // 是否能够不顾RecorverLevel状态而重用部分代码

DO_SNAPSHOT:

            // 快照恢复
            if (level == RecoverLevel.Snapshot
                || bReuse == true)
            {
                string strAction = DomUtil.GetElementText(domLog.DocumentElement,
                    "action");

                string strReaderBarcode = DomUtil.GetElementText(domLog.DocumentElement,
                    "readerBarcode");
                if (String.IsNullOrEmpty(strReaderBarcode) == true)
                {
                    strError = "<readerBarcode>元素值为空";
                    goto ERROR1;
                }

                // 读入读者记录
                string strReaderXml = "";
                string strOutputReaderRecPath = "";
                byte[] reader_timestamp = null;

                nRet = this.GetReaderRecXml(
                    // Channels,
                    channel,
                    strReaderBarcode,
                    out strReaderXml,
                    out strOutputReaderRecPath,
                    out reader_timestamp,
                    out strError);
                if (nRet == 0)
                {
                    if (strAction == "repairreaderside")
                    {
                        strError = "读者证条码号 '" + strReaderBarcode + "' 不存在";
                        goto ERROR1;
                    }

                    // 从实体侧恢复的时候,是允许读者记录不存在的
                }
                if (nRet == -1)
                {
                    strError = "读入证条码号为 '" + strReaderBarcode + "' 的读者记录时发生错误: " + strError;
                    goto ERROR1;
                }

                XmlDocument readerdom = null;
                if (string.IsNullOrEmpty(strReaderXml) == false)
                {
                    nRet = LibraryApplication.LoadToDom(strReaderXml,
                        out readerdom,
                        out strError);
                    if (nRet == -1)
                    {
                        strError = "装载读者记录进入XML DOM时发生错误: " + strError;
                        goto ERROR1;
                    }
                }

                // 校验读者证条码号参数是否和XML记录中完全一致
                if (readerdom != null)
                {
                    string strTempBarcode = DomUtil.GetElementText(readerdom.DocumentElement,
                        "barcode");
                    if (strReaderBarcode != strTempBarcode)
                    {
                        strError = "修复操作被拒绝。因读者证条码号参数 '" + strReaderBarcode + "' 和读者记录中<barcode>元素内的读者证条码号值 '" + strTempBarcode + "' 不一致。";
                        goto ERROR1;
                    }
                }
                
                // 读入册记录
                string strConfirmItemRecPath = DomUtil.GetElementText(domLog.DocumentElement,
                    "confirmItemRecPath");
                string strItemBarcode = DomUtil.GetElementText(domLog.DocumentElement,
                    "itemBarcode");
                if (String.IsNullOrEmpty(strItemBarcode) == true)
                {
                    strError = "<strItemBarcode>元素值为空";
                    goto ERROR1;
                }

                string strItemXml = "";
                string strOutputItemRecPath = "";
                byte[] item_timestamp = null;

                // 如果已经有确定的册记录路径
                if (String.IsNullOrEmpty(strConfirmItemRecPath) == false)
                {
                    string strMetaData = "";
                    lRet = channel.GetRes(strConfirmItemRecPath,
                        out strItemXml,
                        out strMetaData,
                        out item_timestamp,
                        out strOutputItemRecPath,
                        out strError);
                    if (lRet == -1)
                    {
                        strError = "根据strConfirmItemRecPath '" + strConfirmItemRecPath + "' 获得册记录失败: " + strError;
                        goto ERROR1;
                    }

                    // 需要检查记录中的<barcode>元素值是否匹配册条码号


                    // TODO: 如果记录路径所表达的记录不存在,或者其<barcode>元素值和要求的册条码号不匹配,那么都要改用逻辑方法,也就是利用册条码号来获得记录。
                    // 当然,这种情况下,非常要紧的是确保数据库的素质很好,本身没有重条码号的情况出现。
                }
                else
                {
                    // 从册条码号获得册记录
                    List<string> aPath = null;

                    // 获得册记录
                    // return:
                    //      -1  error
                    //      0   not found
                    //      1   命中1条
                    //      >1  命中多于1条
                    nRet = this.GetItemRecXml(
                        // Channels,
                        channel,
                        strItemBarcode,
                        out strItemXml,
                        100,
                        out aPath,
                        out item_timestamp,
                        out strError);
                    if (nRet == 0)
                    {
                        if (strAction == "repairitemside")
                        {
                            strError = "册条码号 '" + strItemBarcode + "' 不存在";
                            goto ERROR1;
                        }

                        // 从读者侧恢复的时候,册条码号不存在是允许的
                        goto CONTINUE_REPAIR;
                    }
                    if (nRet == -1)
                    {
                        strError = "读入册条码号为 '" + strItemBarcode + "' 的册记录时发生错误: " + strError;
                        goto ERROR1;
                    }

                    if (aPath.Count > 1)
                    {

                        strError = "册条码号为 '" + strItemBarcode + "' 的册记录有 " + aPath.Count.ToString() + " 条,但此时comfirmItemRecPath却为空";
                        goto ERROR1;
                    }
                    else
                    {

                        Debug.Assert(nRet == 1, "");
                        Debug.Assert(aPath.Count == 1, "");

                        if (nRet == 1)
                        {
                            strOutputItemRecPath = aPath[0];
                        }
                    }
                }

            CONTINUE_REPAIR:

                XmlDocument itemdom = null;
                if (string.IsNullOrEmpty(strItemXml) == false)
                {
                    nRet = LibraryApplication.LoadToDom(strItemXml,
                        out itemdom,
                        out strError);
                    if (nRet == -1)
                    {
                        strError = "装载册记录进入XML DOM时发生错误: " + strError;
                        goto ERROR1;
                    }

                    // 校验册条码号参数是否和XML记录中完全一致
                    string strTempItemBarcode = DomUtil.GetElementText(itemdom.DocumentElement,
                        "barcode");
                    if (strItemBarcode != strTempItemBarcode)
                    {
                        strError = "修复操作被拒绝。因册条码号参数 '" + strItemBarcode + "' 和册记录中<barcode>元素内的册条码号值 '" + strTempItemBarcode + "' 不一致。";
                        goto ERROR1;
                    }
                }

                if (strAction == "repairreaderside")
                {
                    XmlNode nodeBorrow = readerdom.DocumentElement.SelectSingleNode("borrows/borrow[@barcode='" + strItemBarcode + "']");
                    if (nodeBorrow == null)
                    {
                        strError = "修复操作被拒绝。读者记录 " + strReaderBarcode + " 中并不存在有关册 " + strItemBarcode + " 的借阅信息。";
                        goto ERROR1;
                    }

                    if (itemdom != null)
                    {
                        // 看看册记录中是否有指回读者记录的链
                        string strBorrower = DomUtil.GetElementText(itemdom.DocumentElement,
                            "borrower");
                        if (strBorrower == strReaderBarcode)
                        {
                            strError = "修复操作被拒绝。您所请求要修复的链,本是一条完整正确的链。可直接进行普通还书操作。";
                            goto ERROR1;
                        }
                    }

                    // 移除读者记录侧的链
                    nodeBorrow.ParentNode.RemoveChild(nodeBorrow);

                    byte[] output_timestamp = null;
                    string strOutputPath = "";


                    // 写回读者记录
                    lRet = channel.DoSaveTextRes(strOutputReaderRecPath,
                        readerdom.OuterXml,
                        false,
                        "content,ignorechecktimestamp",
                        reader_timestamp,
                        out output_timestamp,
                        out strOutputPath,
                        out strError);
                    if (lRet == -1)
                        goto ERROR1;
                }
                else if (strAction == "repairitemside")
                {
                    // 看看册记录中是否有指向读者记录的链
                    string strBorrower = DomUtil.GetElementText(itemdom.DocumentElement,
                        "borrower");
                    if (String.IsNullOrEmpty(strBorrower) == true)
                    {
                        strError = "修复操作被拒绝。您所请求要修复的册记录中,本来就没有借阅信息,因此谈不上修复。";
                        goto ERROR1;
                    }

                    if (strBorrower != strReaderBarcode)
                    {
                        strError = "修复操作被拒绝。您所请求要修复的册记录中,并没有指明借阅者是读者 " + strReaderBarcode + "。";
                        goto ERROR1;
                    }

                    // 看看读者记录中是否有指回链条。
                    if (readerdom != null)
                    {
                        XmlNode nodeBorrow = readerdom.DocumentElement.SelectSingleNode("borrows/borrow[@barcode='" + strItemBarcode + "']");
                        if (nodeBorrow != null)
                        {
                            strError = "修复操作被拒绝。您所请求要修复的链,本是一条完整正确的链。可直接进行普通还书操作。";
                            goto ERROR1;
                        }
                    }

                    // 移除册记录侧的链
                    DomUtil.SetElementText(itemdom.DocumentElement,
                        "borrower", "");
                    DomUtil.SetElementText(itemdom.DocumentElement,
                        "borrowDate", "");
                    DomUtil.SetElementText(itemdom.DocumentElement,
                        "borrowPeriod", "");

                    byte[] output_timestamp = null;
                    string strOutputPath = "";

                    // 写回册记录
                    lRet = channel.DoSaveTextRes(strOutputItemRecPath,
                        itemdom.OuterXml,
                        false,
                        "content,ignorechecktimestamp",
                        item_timestamp,
                        out output_timestamp,
                        out strOutputPath,
                        out strError);
                    if (lRet == -1)
                        goto ERROR1;
                }
                else
                {
                    strError = "不可识别的strAction值 '"+strAction+"'";
                    goto ERROR1;
                }

                return 0;
            }

            // 逻辑恢复或者混合恢复
            if (level == RecoverLevel.Logic
                || level == RecoverLevel.LogicAndSnapshot)
            {
                // 和SnapShot方式相同
                bReuse = true;
                goto DO_SNAPSHOT;
            }
            return 0;
        ERROR1:
            if (level == RecoverLevel.LogicAndSnapshot)
            {
                level = RecoverLevel.Snapshot;
                goto DO_SNAPSHOT;
            }
            return -1;
        }
예제 #8
0
        // 填充listview
        public int Fill(string strLang,
                        out string strError)
        {
            listView_users.Items.Clear();
            strError = "";

            string strQueryXml = "<target list='"
                                 + StringUtil.GetXmlStringSimple(Defs.DefaultUserDb.Name) // 2007/9/14
                                 + ":" + "__id'><item><word>"
                                 + "" + "</word><match>left</match><relation>=</relation><dataType>string</dataType><maxCount>10</maxCount></item><lang>zh</lang></target>";

            RmsChannel channel = Channels.GetChannel(this.ServerUrl);

            if (channel == null)
            {
                strError = "Channels.GetChannel 异常";
                return(-1);
            }

            long nRet = channel.DoSearch(strQueryXml,
                                         "default",
                                         "", // strOuputStyle
                                         out strError);

            if (nRet == -1)
            {
                strError = "检索帐户库时出错: " + strError;
                return(-1);
            }

            if (nRet == 0)
            {
                return(0);                      // not found
            }
            long lTotalCount = nRet;            // 总命中数
            long lThisCount  = lTotalCount;
            long lStart      = 0;

            for (;;)
            {
                ArrayList aLine = null;
                nRet = channel.DoGetSearchFullResult(
                    "default",
                    lStart,
                    lThisCount,
                    strLang,
                    null,                       // stop,
                    out aLine,
                    out strError);
                if (nRet == -1)
                {
                    strError = "检索注册用户库获取检索结果时出错: " + strError;
                    return(-1);
                }

                for (int i = 0; i < aLine.Count; i++)
                {
                    string[] acol = (string[])aLine[i];
                    if (acol.Length < 1)
                    {
                        continue;
                    }
                    if (acol.Length < 2)
                    {
                        // 列中没有用户名, 用获取记录来补救?
                    }
                    ListViewItem item = new ListViewItem(acol[1], 0);
                    this.listView_users.Items.Add(item);
                    item.SubItems.Add(acol[0]);
                }


                if (lStart + aLine.Count >= lTotalCount)
                {
                    break;
                }

                lStart     += aLine.Count;
                lThisCount -= aLine.Count;
            }


            return(0);
        }
예제 #9
0
        // Return() API 恢复动作
        /* 日志记录格式
<root>
  <operation>return</operation> 操作类型
  <itemBarcode>0000001</itemBarcode> 册条码号
  <readerBarcode>R0000002</readerBarcode> 读者证条码号
  <operator>test</operator> 操作者
  <operTime>Fri, 08 Dec 2006 04:17:45 GMT</operTime> 操作时间
  <overdues>...</overdues> 超期信息 通常内容为一个字符串,为一个<overdue>元素XML文本片断
  
  <confirmItemRecPath>...</confirmItemRecPath> 辅助判断用的册记录路径
  
  <readerRecord recPath='...'>...</readerRecord>	最新读者记录
  <itemRecord recPath='...'>...</itemRecord>	最新册记录
  
</root>
         * * */
        // parameters:
        //      bForce  是否为容错状态。在容错状态下,如果遇到重复的册条码号,就算做第一条。
        public int RecoverReturn(
            RmsChannelCollection Channels,
            RecoverLevel level,
            XmlDocument domLog,
            bool bForce,
            out string strError)
        {
            strError = "";

            long lRet = 0;
            int nRet = 0;

            RmsChannel channel = Channels.GetChannel(this.WsUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }

        DO_SNAPSHOT:

            // 快照恢复
            if (level == RecoverLevel.Snapshot)
            {
                XmlNode node = null;
                string strReaderXml = DomUtil.GetElementText(domLog.DocumentElement,
                    "readerRecord",
                    out node);
                if (node == null)
                {
                    strError = "日志记录中缺<readerRecord>元素";
                    return -1;
                }
                string strReaderRecPath = DomUtil.GetAttr(node, "recPath");

                string strItemXml = DomUtil.GetElementText(domLog.DocumentElement,
                    "itemRecord",
                    out node);
                if (node == null)
                {
                    strError = "日志记录中缺<itemRecord>元素";
                    return -1;
                }
                string strItemRecPath = DomUtil.GetAttr(node, "recPath");

                byte[] timestamp = null;
                byte[] output_timestamp = null;
                string strOutputPath = "";

                // 写读者记录
                lRet = channel.DoSaveTextRes(strReaderRecPath,
                    strReaderXml,
                    false,
                    "content,ignorechecktimestamp",
                    timestamp,
                    out output_timestamp,
                    out strOutputPath,
                    out strError);
                if (lRet == -1)
                {
                    strError = "写入读者记录 '" + strReaderRecPath + "' 时发生错误: " + strError;
                    return -1;
                }

                // 写册记录
                lRet = channel.DoSaveTextRes(strItemRecPath,
                    strItemXml,
                    false,
                    "content,ignorechecktimestamp",
                    timestamp,
                    out output_timestamp,
                    out strOutputPath,
                    out strError);
                if (lRet == -1)
                {
                    strError = "写入读者记录 '" + strReaderRecPath + "' 时发生错误: " + strError;
                    return -1;
                }


                return 0;
            }


            // 逻辑恢复或者混合恢复
            if (level == RecoverLevel.Logic
                || level == RecoverLevel.LogicAndSnapshot)
            {
                string strRecoverComment = "";

                string strAction = DomUtil.GetElementText(domLog.DocumentElement,
                    "action");

                string strReaderBarcode = DomUtil.GetElementText(domLog.DocumentElement,
                    "readerBarcode");


                // 读入册记录
                string strConfirmItemRecPath = DomUtil.GetElementText(domLog.DocumentElement,
                    "confirmItemRecPath");
                string strItemBarcode = DomUtil.GetElementText(domLog.DocumentElement,
                    "itemBarcode");

                if (String.IsNullOrEmpty(strItemBarcode) == true)
                {
                    strError = "<strItemBarcode>元素值为空";
                    goto ERROR1;
                }

                string strItemXml = "";
                string strOutputItemRecPath = "";
                byte[] item_timestamp = null;

                // 如果已经有确定的册记录路径
                if (String.IsNullOrEmpty(strConfirmItemRecPath) == false)
                {
                    string strMetaData = "";
                    lRet = channel.GetRes(strConfirmItemRecPath,
                        out strItemXml,
                        out strMetaData,
                        out item_timestamp,
                        out strOutputItemRecPath,
                        out strError);
                    if (lRet == -1)
                    {
                        strError = "根据strConfirmItemRecPath '" + strConfirmItemRecPath + "' 获得册记录失败: " + strError;
                        goto ERROR1;
                    }

                    // 需要检查记录中的<barcode>元素值是否匹配册条码号
                }
                else
                {
                    // 从册条码号获得册记录
                    List<string> aPath = null;

                    // 获得册记录
                    // return:
                    //      -1  error
                    //      0   not found
                    //      1   命中1条
                    //      >1  命中多于1条
                    nRet = this.GetItemRecXml(
                        // Channels,
                        channel,
                        strItemBarcode,
                        out strItemXml,
                        100,
                        out aPath,
                        out item_timestamp,
                        out strError);
                    if (nRet == 0)
                    {
                        strError = "册条码号 '" + strItemBarcode + "' 不存在";
                        goto ERROR1;
                    }
                    if (nRet == -1)
                    {
                        strError = "读入册条码号为 '" + strItemBarcode + "' 的册记录时发生错误: " + strError;
                        goto ERROR1;
                    }

                    if (aPath.Count > 1)
                    {

                        if (string.IsNullOrEmpty(strReaderBarcode) == true)
                        {
                            // 发生重条码号的时候,又没有读者证条码号辅助判断
                            if (bForce == false)
                            {
                                strError = "册条码号为 '" + strItemBarcode + "' 的册记录有 " + aPath.Count.ToString() + " 条,但此时日志记录中没有提供读者证条码号辅助判断,无法进行还书操作。";
                                goto ERROR1;
                            }
                            // TODO: 那就至少看看这些册中,哪些表明被人借阅着?如果正巧只有一个人借过,那就...。
                            strRecoverComment += "册条码号 " + strItemBarcode + "有 " + aPath.Count.ToString() + " 条重复记录,而且没有读者证条码号进行辅助选择。";
                        }

                        /*
                        strError = "册条码号为 '" + strItemBarcode + "' 的册记录有 " + aPath.Count.ToString() + " 条,但此时comfirmItemRecPath却为空";
                        goto ERROR1;
                         * */
                        // bItemBarcodeDup = true; // 此时已经需要设置状态。虽然后面可以进一步识别出真正的册记录

                        /*
                        // 构造strDupBarcodeList
                        string[] pathlist = new string[aPath.Count];
                        aPath.CopyTo(pathlist);
                        strDupBarcodeList = String.Join(",", pathlist);
                         * */

                        List<string> aFoundPath = null;
                        List<byte[]> aTimestamp = null;
                        List<string> aItemXml = null;

                        // 从若干重复条码号的册记录中,选出其中符合当前读者证条码号的
                        // return:
                        //      -1  出错
                        //      其他    选出的数量
                        nRet = FindItem(
                            channel,
                            strReaderBarcode,
                            aPath,
                            true,   // 优化
                            out aFoundPath,
                            out aItemXml,
                            out aTimestamp,
                            out strError);
                        if (nRet == -1)
                        {
                            strError = "选择重复条码号的册记录时发生错误: " + strError;
                            goto ERROR1;
                        }

                        if (nRet == 0)
                        {
                            strError = "册条码号 '" + strItemBarcode + "' 检索出的 " + aPath.Count + " 条记录中,没有任何一条其<borrower>元素表明了被读者 '" + strReaderBarcode + "' 借阅。";
                            goto ERROR1;
                        }

                        if (nRet > 1)
                        {
                            if (bForce == true)
                            {
                                // 容错情况下,选择第一个册条码号
                                strOutputItemRecPath = aFoundPath[0];
                                item_timestamp = aTimestamp[0];
                                strItemXml = aItemXml[0];

                                // TODO: 不过,应当在记录中记载注释,表示这是容错处理方式
                                if (string.IsNullOrEmpty(strReaderBarcode) == true)
                                {
                                    strRecoverComment += "经过筛选,仍然有 " + aFoundPath.Count.ToString() + " 条册记录含有借阅者信息(无论什么读者证条码号),那么就只好选择其中第一个册记录 " + strOutputItemRecPath + " 进行还书操作。";
                                }
                                else
                                {
                                    strRecoverComment += "经过筛选,仍然有 " + aFoundPath.Count.ToString() + " 条册记录含有借阅者 '"+strReaderBarcode+"' 信息,那么就只好选择其中第一个册记录 " + strOutputItemRecPath + " 进行还书操作。";
                                }
                            }
                            else
                            {
                                strError = "册条码号为 '" + strItemBarcode + "' 并且<borrower>元素表明为读者 '" + strReaderBarcode + "' 借阅的册记录有 " + aFoundPath.Count.ToString() + " 条,无法进行还书操作。";
                                /*
                                aDupPath = new string[aFoundPath.Count];
                                aFoundPath.CopyTo(aDupPath);
                                 * */
                                goto ERROR1;
                            }
                        }

                        Debug.Assert(nRet == 1, "");

                        strOutputItemRecPath = aFoundPath[0];
                        item_timestamp = aTimestamp[0];
                        strItemXml = aItemXml[0];
                    }
                    else
                    {

                        Debug.Assert(nRet == 1, "");
                        Debug.Assert(aPath.Count == 1, "");

                        if (nRet == 1)
                        {
                            strOutputItemRecPath = aPath[0];
                        }
                    }

                }

                XmlDocument itemdom = null;
                nRet = LibraryApplication.LoadToDom(strItemXml,
                    out itemdom,
                    out strError);
                if (nRet == -1)
                {
                    strError = "装载册记录进入XML DOM时发生错误: " + strError;
                    goto ERROR1;
                }

                ///
                if (String.IsNullOrEmpty(strReaderBarcode) == true)
                {
                    if (bForce == true)
                    {
                        // 容错的情况下,从册记录中获得借者证条码号
                        strReaderBarcode = DomUtil.GetElementText(itemdom.DocumentElement,
                            "borrower");
                        if (String.IsNullOrEmpty(strReaderBarcode) == true)
                        {
                            strError = "在不知道读者证条码号的情况下,册记录中的<borrower>元素值为空。无法进行还书操作。";
                            goto ERROR1;
                        }

                    }
                    else
                    {
                        strError = "日志记录中<readerBarcode>元素值为空";
                        goto ERROR1;
                    }
                }

                // 读入读者记录
                string strReaderXml = "";
                string strOutputReaderRecPath = "";
                byte[] reader_timestamp = null;

                nRet = this.GetReaderRecXml(
                    // Channels,
                    channel,
                    strReaderBarcode,
                    out strReaderXml,
                    out strOutputReaderRecPath,
                    out reader_timestamp,
                    out strError);
                if (nRet == 0)
                {
                    strError = "读者证条码号 '" + strReaderBarcode + "' 不存在";
                    goto ERROR1;
                }
                if (nRet == -1)
                {
                    strError = "读入证条码号为 '" + strReaderBarcode + "' 的读者记录时发生错误: " + strError;
                    goto ERROR1;
                }

                XmlDocument readerdom = null;
                nRet = LibraryApplication.LoadToDom(strReaderXml,
                    out readerdom,
                    out strError);
                if (nRet == -1)
                {
                    strError = "装载读者记录进入XML DOM时发生错误: " + strError;
                    goto ERROR1;
                }

                // 修改读者记录
                // 修改册记录
                nRet = ReturnChangeReaderAndItemRecord(
                    // Channels,
                    channel,
                    strAction,
                    strItemBarcode,
                    strReaderBarcode,
                    domLog,
                    strRecoverComment,
                    ref readerdom,
                    ref itemdom,
                    out strError);
                if (nRet == -1)
                    goto ERROR1;

                // 写回读者、册记录
                byte[] output_timestamp = null;
                string strOutputPath = "";


                // 写回读者记录
                lRet = channel.DoSaveTextRes(strOutputReaderRecPath,
                    readerdom.OuterXml,
                    false,
                    "content,ignorechecktimestamp",
                    reader_timestamp,
                    out output_timestamp,
                    out strOutputPath,
                    out strError);
                if (lRet == -1)
                    goto ERROR1;

                // 写回册记录
                lRet = channel.DoSaveTextRes(strOutputItemRecPath,
                    itemdom.OuterXml,
                    false,
                    "content,ignorechecktimestamp",
                    item_timestamp,
                    out output_timestamp,
                    out strOutputPath,
                    out strError);
                if (lRet == -1)
                    goto ERROR1;

            }


            // 容错恢复
            if (level == RecoverLevel.Robust)
            {
                string strRecoverComment = "";

                string strAction = DomUtil.GetElementText(domLog.DocumentElement,
                    "action");

                string strReaderBarcode = DomUtil.GetElementText(domLog.DocumentElement,
                    "readerBarcode");


                // 读入册记录
                string strConfirmItemRecPath = DomUtil.GetElementText(domLog.DocumentElement,
                    "confirmItemRecPath");
                string strItemBarcode = DomUtil.GetElementText(domLog.DocumentElement,
                    "itemBarcode");

                if (String.IsNullOrEmpty(strItemBarcode) == true)
                {
                    strError = "<strItemBarcode>元素值为空";
                    goto ERROR1;
                }

                string strItemXml = "";
                string strOutputItemRecPath = "";
                byte[] item_timestamp = null;


                // 从册条码号获得册记录
                List<string> aPath = null;

                bool bDupItemBarcode = false;   // 册条码号是否发生了重复

                // 获得册记录
                // return:
                //      -1  error
                //      0   not found
                //      1   命中1条
                //      >1  命中多于1条
                nRet = this.GetItemRecXml(
                    // Channels,
                    channel,
                    strItemBarcode,
                    out strItemXml,
                    100,
                    out aPath,
                    out item_timestamp,
                    out strError);
                if (nRet == 0)
                {
                    strError = "册条码号 '" + strItemBarcode + "' 不存在";
                    // TODO: 记入信息文件

                    XmlNode node = null;
                    strItemXml = DomUtil.GetElementText(domLog.DocumentElement,
                        "itemRecord",
                        out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<itemRecord>元素";
                        return -1;
                    }
                    string strItemRecPath = DomUtil.GetAttr(node, "recPath");
                    if (String.IsNullOrEmpty(strItemRecPath) == true)
                    {
                        strError = "日志记录中<itemRecord>元素缺recPath属性";
                        return -1;
                    }

                    // 新增一条册记录
                    strOutputItemRecPath = ResPath.GetDbName(strItemRecPath) + "/?";
                    item_timestamp = null;
                }
                else
                {
                    if (nRet == -1)
                    {
                        strError = "读入册条码号为 '" + strItemBarcode + "' 的册记录时发生错误: " + strError;
                        return -1;
                    }

                    if (aPath.Count > 1)
                    {
                        bDupItemBarcode = true;

                        if (string.IsNullOrEmpty(strReaderBarcode) == true)
                        {
                            // 发生重条码号的时候,又没有读者证条码号辅助判断
                            if (bForce == false)
                            {
                                strError = "册条码号为 '" + strItemBarcode + "' 的册记录有 " + aPath.Count.ToString() + " 条,但此时日志记录中没有提供读者证条码号辅助判断,无法进行还书操作。";
                                return -1;
                            }
                            // TODO: 那就至少看看这些册中,哪些表明被人借阅着?如果正巧只有一个人借过,那就...。
                            strRecoverComment += "册条码号 " + strItemBarcode + " 有 " + aPath.Count.ToString() + " 条重复记录,而且没有读者证条码号进行辅助选择。";
                        }

                        List<string> aFoundPath = null;
                        List<byte[]> aTimestamp = null;
                        List<string> aItemXml = null;

                        // 从若干重复条码号的册记录中,选出其中符合当前读者证条码号的
                        // return:
                        //      -1  出错
                        //      其他    选出的数量
                        nRet = FindItem(
                            channel,
                            strReaderBarcode,
                            aPath,
                            true,   // 优化
                            out aFoundPath,
                            out aItemXml,
                            out aTimestamp,
                            out strError);
                        if (nRet == -1)
                        {
                            strError = "选择重复条码号的册记录时发生错误: " + strError;
                            return -1;
                        }

                        if (nRet == 0)
                        {
                            if (bDupItemBarcode == false)
                            {
                                // 没有重复册条码号的情况下才作
                                // 需要把根据“所借册条码号”清除读者记录中借阅信息的动作提前进行? 这样遇到特殊情况范围时,至少读者记录中的信息是被清除了的,这是容错的需要
                                string strError_1 = "";
                                nRet = ReturnAllReader(
                                        // Channels,
                                        channel,
                                        strItemBarcode,
                                        "",
                                        out strError_1);
                                if (nRet == -1)
                                {
                                    // 故意不报,继续处理
                                }
                            }

                            strError = "册条码号 '" + strItemBarcode + "' 检索出的 " + aPath.Count + " 条记录中,没有任何一条其<borrower>元素表明了被读者 '" + strReaderBarcode + "' 借阅。";
                            return -1;
                        }

                        if (nRet > 1)
                        {
                            if (bForce == true)
                            {
                                // 容错情况下,选择第一个册条码号
                                strOutputItemRecPath = aFoundPath[0];
                                item_timestamp = aTimestamp[0];
                                strItemXml = aItemXml[0];

                                // TODO: 不过,应当在记录中记载注释,表示这是容错处理方式
                                if (string.IsNullOrEmpty(strReaderBarcode) == true)
                                {
                                    strRecoverComment += "经过筛选,仍然有 " + aFoundPath.Count.ToString() + " 条册记录含有借阅者信息(无论什么读者证条码号),那么就只好选择其中第一个册记录 " + strOutputItemRecPath + " 进行还书操作。";
                                }
                                else
                                {
                                    strRecoverComment += "经过筛选,仍然有 " + aFoundPath.Count.ToString() + " 条册记录含有借阅者 '" + strReaderBarcode + "' 信息,那么就只好选择其中第一个册记录 " + strOutputItemRecPath + " 进行还书操作。";
                                }
                            }
                            else
                            {
                                strError = "册条码号为 '" + strItemBarcode + "' 并且<borrower>元素表明为读者 '" + strReaderBarcode + "' 借阅的册记录有 " + aFoundPath.Count.ToString() + " 条,无法进行还书操作。";
                                return -1;
                            }
                        }

                        Debug.Assert(nRet == 1, "");

                        strOutputItemRecPath = aFoundPath[0];
                        item_timestamp = aTimestamp[0];
                        strItemXml = aItemXml[0];
                    }
                    else
                    {

                        Debug.Assert(nRet == 1, "");
                        Debug.Assert(aPath.Count == 1, "");

                        if (nRet == 1)
                        {
                            strOutputItemRecPath = aPath[0];
                        }
                    }
                }


                ////

                XmlDocument itemdom = null;
                nRet = LibraryApplication.LoadToDom(strItemXml,
                    out itemdom,
                    out strError);
                if (nRet == -1)
                {
                    strError = "装载册记录进入XML DOM时发生错误: " + strError;
                    goto ERROR1;
                }


                ///
                if (String.IsNullOrEmpty(strReaderBarcode) == true)
                {
                    if (bForce == true)
                    {
                        // 容错的情况下,从册记录中获得借者证条码号
                        strReaderBarcode = DomUtil.GetElementText(itemdom.DocumentElement,
                            "borrower");
                        if (String.IsNullOrEmpty(strReaderBarcode) == true)
                        {
                            strError = "在不知道读者证条码号的情况下,册记录中的<borrower>元素值为空。无法进行还书操作。";
                            return -1;
                        }

                    }
                    else
                    {
                        strError = "日志记录中<readerBarcode>元素值为空";
                        return -1;
                    }
                }

                // 读入读者记录
                string strReaderXml = "";
                string strOutputReaderRecPath = "";
                byte[] reader_timestamp = null;

                nRet = this.GetReaderRecXml(
                    // Channels,
                    channel,
                    strReaderBarcode,
                    out strReaderXml,
                    out strOutputReaderRecPath,
                    out reader_timestamp,
                    out strError);
                if (nRet == 0)
                {
                    strError = "读者证条码号 '" + strReaderBarcode + "' 不存在";
                    // TODO: 记入信息文件

                    // 从日志记录中获得读者记录
                    XmlNode node = null;
                    strReaderXml = DomUtil.GetElementText(domLog.DocumentElement,
                        "readerRecord",
                        out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<readerRecord>元素";
                        return -1;
                    }
                    string strReaderRecPath = DomUtil.GetAttr(node, "recPath");
                    if (String.IsNullOrEmpty(strReaderRecPath) == true)
                    {
                        strError = "日志记录中<readerRecord>元素缺recPath属性";
                        return -1;
                    }

                    // 新增一条读者记录
                    strOutputReaderRecPath = ResPath.GetDbName(strReaderRecPath) + "/?";
                    reader_timestamp = null;
                }
                else
                {
                    if (nRet == -1)
                    {
                        strError = "读入证条码号为 '" + strReaderBarcode + "' 的读者记录时发生错误: " + strError;
                        return -1;
                    }
                }

                XmlDocument readerdom = null;
                nRet = LibraryApplication.LoadToDom(strReaderXml,
                    out readerdom,
                    out strError);
                if (nRet == -1)
                {
                    strError = "装载读者记录进入XML DOM时发生错误: " + strError;
                    return -1;
                }


                // 修改读者记录
                // 修改册记录
                nRet = ReturnChangeReaderAndItemRecord(
                    // Channels,
                    channel,
                    strAction,
                    strItemBarcode,
                    strReaderBarcode,
                    domLog,
                    strRecoverComment,
                    ref readerdom,
                    ref itemdom,
                    out strError);
                if (nRet == -1)
                    return -1;

                // 在容错(并且没有重复册条码号的情况下)的情况下,需要利用读者库的“所借册条码号”检索途径,把除了当前关注的读者记录以外的潜在相关读者记录调出,
                // 把它们中的相关<borrows/borrow>抹除,以免造成多头的借阅信息。
                if (bDupItemBarcode == false)
                {
                    nRet = ReturnAllReader(
                            // Channels,
                            channel,
                            strItemBarcode,
                            strOutputReaderRecPath,
                            out strError);
                    if (nRet == -1)
                    {
                        // 故意不报,继续处理
                    }
                }


                ////



                // 写回读者、册记录
                byte[] output_timestamp = null;
                string strOutputPath = "";


                // 写回读者记录
                lRet = channel.DoSaveTextRes(strOutputReaderRecPath,
                    readerdom.OuterXml,
                    false,
                    "content,ignorechecktimestamp",
                    reader_timestamp,
                    out output_timestamp,
                    out strOutputPath,
                    out strError);
                if (lRet == -1)
                    return -1;

                // 写回册记录
                lRet = channel.DoSaveTextRes(strOutputItemRecPath,
                    itemdom.OuterXml,
                    false,
                    "content,ignorechecktimestamp",
                    item_timestamp,
                    out output_timestamp,
                    out strOutputPath,
                    out strError);
                if (lRet == -1)
                    return -1;

            }



            return 0;
        ERROR1:
            if (level == RecoverLevel.LogicAndSnapshot)
            {
                level = RecoverLevel.Snapshot;
                goto DO_SNAPSHOT;
            }
            return -1;
        }
예제 #10
0
        private void button_OK_Click(object sender, System.EventArgs e)
        {
            if (textBox_url.Text == "")
            {
                MessageBox.Show(this, "尚未指定服务器URL...");
                return;
            }

            if (textBox_newPassword.Text != textBox_newPasswordConfirm.Text)
            {
                MessageBox.Show(this, "新密码和确认密码不一致,请重新输入...");
                return;
            }

            if (textBox_userName.Text == "")
            {
                MessageBox.Show(this, "尚未输入用户名。");
                return;
            }

            channel = Channels.GetChannel(textBox_url.Text);
            Debug.Assert(channel != null, "Channels.GetChannel 异常");

            stop.OnStop += new StopEventHandler(this.DoStop);
            stop.Initial("正在修改密码...");

            stop.BeginLoop();

            int    nRet;
            string strError;

            EnableControls(false);
            button_Cancel.Text = "中断";


            nRet = channel.ChangePassword(
                textBox_userName.Text,
                textBox_oldPassword.Text,
                textBox_newPassword.Text,
                checkBox_manager.Checked,
                out strError);

            EnableControls(true);

            stop.EndLoop();

            stop.OnStop -= new StopEventHandler(this.DoStop);
            stop.Initial("");

            button_Cancel.Enabled = true;       // 因为Cancel按钮还有退出对话框的功能
            button_Cancel.Text    = "取消";

            if (nRet == -1)
            {
                goto ERROR1;
            }

            channel = null;

            MessageBox.Show(this, "密码修改成功。");

            this.DialogResult = DialogResult.OK;
            this.Close();
            return;

ERROR1:
            button_Cancel.Enabled = true;
            button_Cancel.Text    = "取消";

            channel = null;
            MessageBox.Show(this, "修改密码失败,原因:" + strError);
        }
예제 #11
0
        // 递归
        public int Fill(TreeNode node)
        {
            TreeNodeCollection children = null;

            if (node == null)
            {
                children = this.Nodes;
            }
            else
            {
                children = node.Nodes;
            }

            int i;


            // 填充根
            if (node == null)
            {
                children.Clear();

                TreeNode nodeNew = new TreeNode(this.ServerUrl, ResTree.RESTYPE_SERVER, ResTree.RESTYPE_SERVER);
                ResTree.SetLoading(nodeNew);

                NodeInfo nodeinfo = new NodeInfo();
                nodeinfo.TreeNode   = nodeNew;
                nodeinfo.Expandable = true;
                nodeinfo.DefElement = GetDefElementString(nodeNew.ImageIndex);
                nodeinfo.NodeState |= NodeState.Object;

                nodeNew.Tag = nodeinfo;


                if (EnabledIndices != null &&
                    StringUtil.IsInList(nodeNew.ImageIndex, EnabledIndices) == false)
                {
                    nodeNew.ForeColor = ControlPaint.LightLight(nodeNew.ForeColor);
                }

                children.Add(nodeNew);
                return(0);
            }


            // 根以下的节点类型
            ResPath respath = new ResPath(node);

            string strPath = respath.Path;

            //if (node != null)
            //	strPath = TreeViewUtil.GetPath(node);

            this.channel = Channels.GetChannel(this.ServerUrl);

            Debug.Assert(channel != null, "Channels.GetChannel() 异常");

            ResInfoItem[] items = null;

            string strError = "";

            DigitalPlatform.Stop stop = null;

            if (stopManager != null)
            {
                stop = new DigitalPlatform.Stop();

                stop.Register(this.stopManager, true);  // 和容器关联

                stop.OnStop += new StopEventHandler(this.DoStop);
                stop.Initial("正在列目录: " + this.ServerUrl + "?" + strPath);
                stop.BeginLoop();
            }

            long lRet = channel.DoDir(strPath,
                                      this.Lang,
                                      null, // 不需要列出全部语言的名字
                                      out items,
                                      out strError);

            if (stopManager != null)
            {
                stop.EndLoop();
                stop.OnStop -= new StopEventHandler(this.DoStop);
                stop.Initial("");

                stop.Unregister();      // 和容器关联
            }

            this.channel = null;

            if (lRet == -1)
            {
                try
                {
                    MessageBox.Show(this, "Channel::DoDir() Error: " + strError);
                }
                catch
                {
                    // this可能已经不存在
                    return(-1);
                }

                if (node != null)
                {
                    ResTree.SetLoading(node);   // 出错的善后处理,重新出现+号
                    node.Collapse();
                }
                return(-1);
            }


            if (items != null)
            {
                children.Clear();

                for (i = 0; i < items.Length; i++)
                {
                    // 忽略from类型节点
                    if (items[i].Type == ResTree.RESTYPE_FROM)
                    {
                        continue;
                    }

                    TreeNode nodeNew = new TreeNode(items[i].Name, items[i].Type, items[i].Type);


                    NodeInfo nodeinfo = new NodeInfo();
                    nodeinfo.TreeNode   = nodeNew;
                    nodeinfo.Expandable = items[i].HasChildren;
                    nodeinfo.DefElement = GetDefElementString(nodeNew.ImageIndex);
                    nodeinfo.NodeState |= NodeState.Object;
                    nodeinfo.Style      = items[i].Style;
                    nodeNew.Tag         = nodeinfo;

                    if (items[i].HasChildren)
                    {
                        ResTree.SetLoading(nodeNew);
                    }

                    if (EnabledIndices != null &&
                        StringUtil.IsInList(nodeNew.ImageIndex, EnabledIndices) == false)
                    {
                        nodeNew.ForeColor = ControlPaint.LightLight(nodeNew.ForeColor);
                    }

                    children.Add(nodeNew);
                }
            }

            return(0);
        }
예제 #12
0
        // 检索文章
        // return:
        //		-1	error
        //		其他 命中数
        public int Search(
            string strServerUrl,
            string strQueryXml,
            RmsChannelCollection Channels,
            string strLang,
            out string strError)
        {
            strError = "";

            string strMessage = "";

            // 加写锁
            this.m_lock.AcquireWriterLock(m_nLockTimeout);
            try
            {
                this.File.Clear();      // 清空集合


                //if (page.Response.IsClientConnected == false)	// 灵敏中断
                //	return -1;

                RmsChannel channel = Channels.GetChannel(strServerUrl);
                Debug.Assert(channel != null, "Channels.GetChannel 异常");

                strMessage += "--- begin search ...\r\n";

                DateTime time = DateTime.Now;

                //if (page.Response.IsClientConnected == false)	// 灵敏中断
                //	return -1;

                long nRet = channel.DoSearch(strQueryXml,
                                             "default",
                                             "", // strOuputStyle
                                             out strError);
                if (nRet == -1)
                {
                    strError = "检索时出错: " + strError;
                    return(-1);
                }


                TimeSpan delta = DateTime.Now - time;
                strMessage += "search end. time=" + delta.ToString() + "\r\n";

                if (nRet == 0)
                {
                    return(0);   // not found
                }
                long lTotalCount = nRet;

                //if (page.Response.IsClientConnected == false)	// 灵敏中断
                //	return -1;

                strMessage += "--- begin get search result ...\r\n";

                time = DateTime.Now;

                long lStart    = 0;
                long lPerCount = Math.Min(lTotalCount, 1000);


                for (; ;)
                {
                    //if (page.Response.IsClientConnected == false)	// 灵敏中断
                    //	return -1;


                    lPerCount = Math.Min((lTotalCount - lStart), 1000);

                    nRet = channel.DoGetSearchResult(
                        "default",
                        lStart,
                        lPerCount,
                        strLang,
                        null,   // stop,
                        out List <string> aPath,
                        out strError);
                    if (nRet == -1)
                    {
                        strError = "检索库时出错: " + strError;
                        return(-1);
                    }

                    delta       = DateTime.Now - time;
                    strMessage += "get search result end. time=" + delta.ToString() + "\r\n";

                    if (aPath.Count == 0)
                    {
                        strError = "检索库时获取的检索结果为空";
                        return(-1);
                    }

                    //if (page.Response.IsClientConnected == false)	// 灵敏中断
                    //	return -1;

                    strMessage += "--- begin build storage ...\r\n";

                    time = DateTime.Now;

                    int i;
                    // 加入新行对象。新行对象中,只初始化了m_strRecID参数
                    for (i = 0; i < aPath.Count; i++)
                    {
                        ClientRecordItem item = new ClientRecordItem();
                        item.Path = (string)aPath[i];
                        this.File.Add(item);

                        if ((i % 100) == 0)
                        {
                            strMessage += "process " + Convert.ToString(i) + "\r\n";
                        }
                    }

                    delta       = DateTime.Now - time;
                    strMessage += "build storage end. time=" + delta.ToString() + "\r\n";

                    lStart += aPath.Count;
                    if (lStart >= lTotalCount)
                    {
                        break;
                    }
                }


                return(1);
            }
            finally
            {
                this.m_lock.ReleaseWriterLock();
            }
        }
예제 #13
0
파일: AppIssue.cs 프로젝트: renyh1013/dp2
        // 获得期刊记录
        // 本函数可获得超过1条以上的路径
        // parameters:
        //      timestamp   返回命中的第一条的timestamp
        // return:
        //      -1  error
        //      0   not found
        //      1   命中1条
        //      >1  命中多于1条
        public int GetIssueRecXml(
            RmsChannelCollection channels,
            string strIssueDbName,
            string strParentID,
            string strPublishTime,
            out string strXml,
            int nMax,
            out List<string> aPath,
            out byte[] timestamp,
            out string strError)
        {
            aPath = null;

            strXml = "";
            strError = "";
            timestamp = null;

            LibraryApplication app = this;

            // 构造检索式
            // 构造检索式
            string strQueryXml = "<target list='"
                    + StringUtil.GetXmlStringSimple(strIssueDbName + ":" + "出版时间")
                    + "'><item><word>"
                    + StringUtil.GetXmlStringSimple(strPublishTime)
                    + "</word><match>exact</match><relation>=</relation><dataType>string</dataType><maxCount>-1</maxCount></item><lang>zh</lang></target>";

            strQueryXml += "<operator value='AND'/>";


            strQueryXml += "<target list='"
                    + StringUtil.GetXmlStringSimple(strIssueDbName + ":" + "父记录")
                    + "'><item><word>"
                    + StringUtil.GetXmlStringSimple(strParentID)
                    + "</word><match>exact</match><relation>=</relation><dataType>string</dataType><maxCount>-1</maxCount></item><lang>zh</lang></target>";

            strQueryXml = "<group>" + strQueryXml + "</group>";

            RmsChannel channel = channels.GetChannel(app.WsUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }

            long lRet = channel.DoSearch(strQueryXml,
                "default",
                out strError);
            if (lRet == -1)
                goto ERROR1;

            // not found
            if (lRet == 0)
            {
                strError = "册条码号 '" + strPublishTime + "' 没有找到";
                return 0;
            }

            long lHitCount = lRet;

            // List<string> aPath = null;
            lRet = channel.DoGetSearchResult(
                "default",
                0,
                Math.Min(nMax, lHitCount),
                "zh",
                null,
                out aPath,
                out strError);
            if (lRet == -1)
                goto ERROR1;

            Debug.Assert(aPath != null, "");

            if (aPath.Count == 0)
            {
                strError = "DoGetSearchResult aPath error";
                goto ERROR1;
            }

            string strMetaData = "";
            string strOutputPath = "";

            lRet = channel.GetRes(aPath[0],
                out strXml,
                out strMetaData,
                out timestamp,
                out strOutputPath,
                out strError);
            if (lRet == -1)
                goto ERROR1;

            return (int)lHitCount;
        ERROR1:
            return -1;
        }
예제 #14
0
파일: AppIssue.cs 프로젝트: renyh1013/dp2
        // 根据 父记录ID/出版时间 对期库进行查重
        // 本函数只负责查重, 并不获得记录体
        // return:
        //      -1  error
        //      其他    命中记录条数(不超过nMax规定的极限)
        public int SearchIssueRecDup(
            RmsChannelCollection channels,
            string strIssueDbName,
            string strParentID,
            string strPublishTime,
            int nMax,
            out List<string> aPath,
            out string strError)
        {
            strError = "";
            aPath = null;

            LibraryApplication app = this;

            // 构造检索式
            string strQueryXml = "<target list='"
                    + StringUtil.GetXmlStringSimple(strIssueDbName + ":" + "出版时间")
                    + "'><item><word>"
                    + StringUtil.GetXmlStringSimple(strPublishTime)
                    + "</word><match>exact</match><relation>=</relation><dataType>string</dataType><maxCount>-1</maxCount></item><lang>zh</lang></target>";

            strQueryXml += "<operator value='AND'/>";


            strQueryXml += "<target list='"
                    + StringUtil.GetXmlStringSimple(strIssueDbName + ":" + "父记录")
                    + "'><item><word>"
                    + StringUtil.GetXmlStringSimple(strParentID)
                    + "</word><match>exact</match><relation>=</relation><dataType>string</dataType><maxCount>-1</maxCount></item><lang>zh</lang></target>";

            strQueryXml = "<group>" + strQueryXml + "</group>";

            RmsChannel channel = channels.GetChannel(app.WsUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }

            long lRet = channel.DoSearch(strQueryXml,
                "default",
                out strError);
            if (lRet == -1)
                goto ERROR1;

            // not found
            if (lRet == 0)
            {
                strError = "出版时间为 '" + strPublishTime + "' 并且 父记录为 '"+strParentID+"' 的记录没有找到";
                return 0;
            }

            long lHitCount = lRet;

            lRet = channel.DoGetSearchResult(
                "default",
                0,
                nMax,
                "zh",
                null,
                out aPath,
                out strError);
            if (lRet == -1)
                goto ERROR1;

            if (aPath.Count == 0)
            {
                strError = "DoGetSearchResult aPath error 和前面已经命中的条件矛盾";
                goto ERROR1;
            }

            return (int)lHitCount;
        ERROR1:
            return -1;
        }
예제 #15
0
        // 检索获得消息, 或者从结果集中获得消息
        // parameters:
        //      strStyle    search / untouched / touched
        //                  有search表示进行检索和获取,没有search就表示不检索而获取先前检索的结果集。
        //                  untoched和touched应当和search联用。否则只能获取先前的结果数
        public int GetMessage(
            RmsChannelCollection Channels,
            string strResultsetName,
            string strStyle,
            string strUserID,
            string strBoxType,
            MessageLevel messagelevel,
            int nStart,
            int nCount,
            out int nTotalCount,
            out List<MessageData> messages,
            out string strError)
        {
            nTotalCount = 0;
            messages = new List<MessageData>();
            strError = "";

            if (String.IsNullOrEmpty(this.MessageDbName) == true)
            {
                strError = "消息库尚未定义";
                return -1;
            }

            int nRet = 0;
            long lRet = 0;

            if (String.IsNullOrEmpty(strBoxType) == true)
            {
                strBoxType = MessageCenter.INBOX;
            }

            RmsChannel channel = Channels.GetChannel(this.ServerUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }


            if (String.IsNullOrEmpty(strResultsetName) == true)
                strResultsetName = "messages_of_" + strBoxType;

            bool bSearch = true;
            if (StringUtil.IsInList("search", strStyle) == true)
                bSearch = true;
            else
                bSearch = false;

            string strQueryStyle = "";
            if (StringUtil.IsInList("touched", strStyle) == true)
                strQueryStyle = "touched";
            else if (StringUtil.IsInList("untouched", strStyle) == true)
                strQueryStyle = "untouched";

            // 检索
            if (bSearch == true)
            {

                string strQueryXml = "";

                // 构造检索式
                nRet = MakeSearchQuery(
                    strUserID,
                    strBoxType,
                    strQueryStyle,
                    out strQueryXml,
                    out strError);
                if (nRet == -1)
                {
                    // text-level: 内部错误
                    strError = "构造检索式出错: " + strError;
                    return -1;
                }


                lRet = channel.DoSearch(strQueryXml,
                    strResultsetName,
                    "", // strOuputStyle
                    out strError);
                if (lRet == -1)
                {
                    // text-level: 内部错误
                    strError = "检索失败: " + strError;
                    return -1;
                }

                // not found
                if (lRet == 0)
                {
                    // text-level: 用户提示
                    strError = this.GetString("没有任何消息");  // "没有任何消息"
                    return 0;
                }

                nTotalCount = (int)lRet;
            }


            if (nCount == 0)
                return nTotalCount;   // 如果不需要获得结果集

            Debug.Assert(nStart >= 0, "");


            // 获得结果集中指定范围的记录路径
            ArrayList aLine = null;
            lRet = channel.DoGetSearchFullResult(
                strResultsetName,
                nStart,
                nCount,
                "zh",
                null,
                out aLine,
                out strError);
            if (lRet == -1)
            {
                // 虽然返回-1,但是aLine中仍然有内容了
                if (aLine == null)
                {
                    // text-level: 内部错误
                    strError = "获取浏览格式失败: " + strError;
                    return -1;
                }
            }

            // 返回数据
            for (int i = 0; i < aLine.Count; i++)
            {
                string[] cols = null;

                cols = (string[])aLine[i];

                string strPath = cols[0];

                MessageData data = null;

                // TODO: level == none 只返回路径
                nRet = GetMessageByPath(
                    channel,
                    strPath,
                    messagelevel,
                    out data,
                    out strError);
                if (nRet == -1)
                    return -1;

                messages.Add(data);

            }

            return aLine.Count;
        }
예제 #16
0
        // 通过特定检索途径获得读者记录的特定keys值
        // return:
        //      -1  error
        //      >=0 命中个数
        public int SearchAllIds(
            RmsChannelCollection channels,
            string strPatronDbName,
            string strFrom,
            out List<string> ids,
            out string strError)
        {
            strError = "";
            ids = new List<string>();

            Debug.Assert(String.IsNullOrEmpty(strPatronDbName) == false, "");
            // 构造检索式
            string strQueryXml = "<target list='"
                    + StringUtil.GetXmlStringSimple(strPatronDbName + ":" + strFrom)
                    + "'><item><word></word><match>left</match><relation>=</relation><dataType>string</dataType><maxCount>-1</maxCount></item><lang>zh</lang></target>";

            RmsChannel channel = channels.GetChannel(this.App.WsUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }

            string strOutputStyle = "keyid";
            string strBrowseStyle = "keyid,key,id,cols";


            long lRet = channel.DoSearch(strQueryXml,
                "default",
                strOutputStyle,
                out strError);
            if (lRet == -1)
                goto ERROR1;

            // not found
            if (lRet == 0)
                return 0;

            long lHitCount = lRet;
            long lStart = 0;
            for (; ; )
            {
#if NO
                // 2012/2/4
                // 系统挂起的时候,不运行本线程
                if (this.App.HangupReason == HangupReason.LogRecover)
                {
                    strError = "因为系统挂起或暂停批处理而中断处理";
                    return -1;
                }
#endif
                if (this.Stopped == true)
                {
                    strError = "中断处理";
                    return -1;
                }

                Record[] records = null;
                lRet = channel.DoGetSearchResult(
                    "default",
                    lStart,
                    -1,
                    strBrowseStyle,
                    "zh",
                    null,
                    out records,
                    out strError);
                if (lRet == -1)
                    goto ERROR1;

                foreach (Record record in records)
                {
                    Debug.Assert(record.Keys != null && record.Keys.Length > 0, "");
                    if (record.Keys != null && record.Keys.Length > 0)
                        ids.Add(record.Keys[0].Key);
                }

                lStart += records.Length;
                if (lStart >= lHitCount)
                    break;
            }

            return (int)lHitCount;
        ERROR1:
            return -1;
        }
예제 #17
0
파일: Util.cs 프로젝트: renyh1013/dp2
        /// <summary>
        /// 检索实用库
        /// </summary>
        /// <param name="Channels"></param>
        /// <param name="strServerUrl"></param>
        /// <param name="strDbName"></param>
        /// <param name="strFrom"></param>
        /// <param name="strKey"></param>
        /// <param name="strXml"></param>
        /// <param name="strError"></param>
        /// <returns></returns>
        public static int SearchUtilDb(
            RmsChannelCollection Channels,
            string strServerUrl,
            string strDbName,
            string strFrom,
            string strKey,
            out string strXml,
            out string strError)
        {
            strError = "";
            strXml = "";

            RmsChannel channel = Channels.GetChannel(strServerUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }


            string[] paths = null;

            int nRet = SearchPath(channel,
                strDbName,
                strFrom,
                strKey,
                1,
                out paths,
                out strError);
            if (nRet == -1)
                return -1;
            if (nRet == 0)
                return 0;

            string strPath = paths[0];

            // 取记录
            string strStyle = "content,data,timestamp";

            string strMetaData;
            string strOutputPath;
            byte[] baTimeStamp = null;

            long lRet = channel.GetRes(strPath,
                strStyle,
                out strXml,
                out strMetaData,
                out baTimeStamp,
                out strOutputPath,
                out strError);
            if (lRet == -1)
            {
                strError = "检索 '" + strPath + "' 记录体时出错: " + strError;
                return -1;
            }


            return 1;
        }
예제 #18
0
        // SetEntities() API 恢复动作
        /* 日志记录格式
<root>
  <operation>setEntity</operation> 操作类型
  <action>new</action> 具体动作。有new change delete 3种
  <style>...</style> 风格。有force nocheckdup noeventlog 3种
  <record recPath='中文图书实体/3'><root><parent>2</parent><barcode>0000003</barcode><state>状态2</state><location>阅览室</location><price></price><bookType>教学参考</bookType><registerNo></registerNo><comment>test</comment><mergeComment></mergeComment><batchNo>111</batchNo><borrower></borrower><borrowDate></borrowDate><borrowPeriod></borrowPeriod></root></record> 记录体
  <oldRecord recPath='中文图书实体/3'>...</oldRecord> 被覆盖或者删除的记录 动作为change和delete时具备此元素
  <operator>test</operator> 操作者
  <operTime>Fri, 08 Dec 2006 08:41:46 GMT</operTime> 操作时间
</root>

注:1) 当<action>为delete时,没有<record>元素。为new时,没有<oldRecord>元素。
	2) <record>中的内容, 涉及到流通的<borrower><borrowDate><borrowPeriod>等, 在日志恢复阶段, 都应当无效, 这几个内容应当从当前位置库中记录获取, 和<record>中其他内容合并后, 再写入数据库
	3) 一次SetEntities()API调用, 可能创建多条日志记录。
         
         * */
        // TODO: 要兑现style中force nocheckdup功能
        public int RecoverSetEntity(
            RmsChannelCollection Channels,
            RecoverLevel level,
            XmlDocument domLog,
            out string strError)
        {
            strError = "";

            long lRet = 0;
            int nRet = 0;

            RmsChannel channel = Channels.GetChannel(this.WsUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }

            bool bReuse = false;    // 是否能够不顾RecorverLevel状态而重用部分代码

        DO_SNAPSHOT:

            string strAction = DomUtil.GetElementText(domLog.DocumentElement,
                "action");

            // 快照恢复
            if (level == RecoverLevel.Snapshot
                || bReuse == true)
            {

                byte[] timestamp = null;
                byte[] output_timestamp = null;
                string strOutputPath = "";

                if (strAction == "new" 
                    || strAction == "change"
                    || strAction == "move")
                {
                    XmlNode node = null;
                    string strRecord = DomUtil.GetElementText(domLog.DocumentElement,
                        "record",
                        out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<record>元素";
                        return -1;
                    }

                    string strNewRecPath = DomUtil.GetAttr(node, "recPath");

                    // 
                    string strOldRecord = "";
                    string strOldRecPath = "";
                    if (strAction == "move")
                    {
                        strOldRecord = DomUtil.GetElementText(domLog.DocumentElement,
                            "oldRecord",
                            out node);
                        if (node == null)
                        {
                            strError = "日志记录中缺<oldRecord>元素";
                            return -1;
                        }

                        strOldRecPath = DomUtil.GetAttr(node, "recPath");
                    }

                    // 写册记录
                    lRet = channel.DoSaveTextRes(strNewRecPath,
                        strRecord,
                        false,
                        "content,ignorechecktimestamp",
                        timestamp,
                        out output_timestamp,
                        out strOutputPath,
                        out strError);
                    if (lRet == -1)
                    {
                        strError = "写入册记录 '" + strNewRecPath + "' 时发生错误: " + strError;
                        return -1;
                    }

                    if (strAction == "move")
                    {
                        // 删除册记录
                        int nRedoCount = 0;

                    REDO_DELETE:
                        lRet = channel.DoDeleteRes(strOldRecPath,
                            timestamp,
                            out output_timestamp,
                            out strError);
                        if (lRet == -1)
                        {
                            if (channel.ErrorCode == ChannelErrorCode.NotFound)
                                return 0;   // 记录本来就不存在

                            if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch)
                            {
                                if (nRedoCount < 10)
                                {
                                    timestamp = output_timestamp;
                                    nRedoCount++;
                                    goto REDO_DELETE;
                                }
                            }
                            strError = "删除册记录 '" + strOldRecPath + "' 时发生错误: " + strError;
                            return -1;

                        }
                    }
                     
                }
                else if (strAction == "delete")
                {
                    XmlNode node = null;
                    string strOldRecord = DomUtil.GetElementText(domLog.DocumentElement,
                        "oldRecord",
                        out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<oldRecord>元素";
                        return -1;
                    }
                    string strRecPath = DomUtil.GetAttr(node, "recPath");

                    int nRedoCount = 0;
                REDO:
                    // 删除册记录
                    lRet = channel.DoDeleteRes(strRecPath,
                        timestamp,
                        out output_timestamp,
                        out strError);
                    if (lRet == -1)
                    {
                        if (channel.ErrorCode == ChannelErrorCode.NotFound)
                            return 0;   // 记录本来就不存在
                        if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch)
                        {
                            if (nRedoCount < 10)
                            {
                                timestamp = output_timestamp;
                                nRedoCount++;
                                goto REDO;
                            }
                        }
                        strError = "删除册记录 '" + strRecPath + "' 时发生错误: " + strError;
                        return -1;

                    }
                }
                else
                {
                    strError = "无法识别的<action>内容 '" + strAction + "'";
                    return -1;
                }


                return 0;
            }

            bool bForce = false;
            bool bNoCheckDup = false;

            string strStyle = DomUtil.GetElementText(domLog.DocumentElement,
                "style");

            if (StringUtil.IsInList("force", strStyle) == true)
                bForce = true;

            if (StringUtil.IsInList("nocheckdup", strStyle) == true)
                bNoCheckDup = true;

            // 逻辑恢复或者混合恢复
            if (level == RecoverLevel.Logic
                || level == RecoverLevel.LogicAndSnapshot)
            {



                // 和数据库中已有记录合并,然后保存
                if (strAction == "new"
                    || strAction == "change"
                    || strAction == "move")
                {
                    XmlNode node = null;
                    string strRecord = DomUtil.GetElementText(domLog.DocumentElement,
                        "record",
                        out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<record>元素";
                        return -1;
                    }

                    string strNewRecPath = DomUtil.GetAttr(node, "recPath");

                    // 
                    string strOldRecord = "";
                    string strOldRecPath = "";
                    if (strAction == "move")
                    {
                        strOldRecord = DomUtil.GetElementText(domLog.DocumentElement,
                            "oldRecord",
                            out node);
                        if (node == null)
                        {
                            strError = "日志记录中缺<oldRecord>元素";
                            return -1;
                        }

                        strOldRecPath = DomUtil.GetAttr(node, "recPath");
                    }


                    // 读出数据库中原有的记录
                    string strExistXml = "";
                    string strMetaData = "";
                    byte[] exist_timestamp = null;
                    string strOutputPath = "";

                    if ((strAction == "change" 
                        || strAction == "move")
                        && bForce == false) // 2008/10/6
                    {
                        string strSourceRecPath = "";

                        if (strAction == "change")
                            strSourceRecPath = strNewRecPath;
                        if (strAction == "move")
                            strSourceRecPath = strOldRecPath;

                        lRet = channel.GetRes(strSourceRecPath,
                            out strExistXml,
                            out strMetaData,
                            out exist_timestamp,
                            out strOutputPath,
                            out strError);
                        if (lRet == -1)
                        {
                            // 容错
                            if (channel.ErrorCode == ChannelErrorCode.NotFound
                                && level == RecoverLevel.LogicAndSnapshot)
                            {
                                // 如果记录不存在, 则构造一条空的记录
                                // bExist = false;
                                strExistXml = "<root />";
                                exist_timestamp = null;
                            }
                            else
                            {
                                strError = "在读入原有记录 '"+strNewRecPath+"' 时失败: " + strError;
                                goto ERROR1;
                            }
                        }
                    }

                    //
                    // 把两个记录装入DOM

                    XmlDocument domExist = new XmlDocument();
                    XmlDocument domNew = new XmlDocument();

                    try
                    {
                        // 防范空记录
                        if (String.IsNullOrEmpty(strExistXml) == true)
                            strExistXml = "<root />";

                        domExist.LoadXml(strExistXml);
                    }
                    catch (Exception ex)
                    {
                        strError = "strExistXml装载进入DOM时发生错误: " + ex.Message;
                        goto ERROR1;
                    }

                    try
                    {
                        domNew.LoadXml(strRecord);
                    }
                    catch (Exception ex)
                    {
                        strError = "strRecord装载进入DOM时发生错误: " + ex.Message;
                        goto ERROR1;
                    }

                    // 合并新旧记录
                    string strNewXml = "";

                    if (bForce == false)
                    {
                        nRet = MergeTwoEntityXml(domExist,
                            domNew,
                            out strNewXml,
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;
                    }
                    else
                    {
                        strNewXml = domNew.OuterXml;
                    }

                    // 保存新记录
                    byte[] output_timestamp = null;

                    if (strAction == "move")
                    {
                        // 复制源记录到目标位置,然后自动删除源记录
                        // 但是尚未在目标位置写入最新内容
                        lRet = channel.DoCopyRecord(strOldRecPath,
                            strNewRecPath,
                            true,   // bDeleteSourceRecord
                            out output_timestamp,
                            out strOutputPath,
                            out strError);
                        if (lRet == -1)
                            goto ERROR1;

                        exist_timestamp = output_timestamp; // 及时更新时间戳
                    }


                    lRet = channel.DoSaveTextRes(strNewRecPath,
                        strNewXml,
                        false,   // include preamble?
                        "content,ignorechecktimestamp",
                        exist_timestamp,
                        out output_timestamp,
                        out strOutputPath,
                        out strError);
                    if (lRet == -1)
                        goto ERROR1;

                    /*
                    if (strAction == "move")
                    {
                        // 删除册记录
                        int nRedoCount = 0;

                        byte[] timestamp = null;

                    REDO_DELETE:
                        lRet = channel.DoDeleteRes(strOldRecPath,
                            timestamp,
                            out output_timestamp,
                            out strError);
                        if (lRet == -1)
                        {
                            if (channel.ErrorCode == ChannelErrorCode.NotFound)
                                return 0;   // 记录本来就不存在

                            if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch)
                            {
                                if (nRedoCount < 10)
                                {
                                    timestamp = output_timestamp;
                                    nRedoCount++;
                                    goto REDO_DELETE;
                                }
                            }
                            strError = "删除册记录 '" + strRecPath + "' 时发生错误: " + strError;
                            return -1;

                        }
                    }
                     * */
                }
                else if (strAction == "delete")
                {
                    // 和SnapShot方式相同
                    bReuse = true;
                    goto DO_SNAPSHOT;
                }
                else
                {
                    strError = "无法识别的<action>内容 '" + strAction + "'";
                    return -1;
                }
            }

            // 容错恢复
            if (level == RecoverLevel.Robust)
            {
                if (strAction == "move")
                {
                    strError = "暂不支持SetEntity的move恢复操作";
                    return -1;
                }

                // 和数据库中已有记录合并,然后保存
                if (strAction == "change" || strAction == "new")
                {
                    XmlNode node = null;
                    string strRecord = DomUtil.GetElementText(domLog.DocumentElement,
                        "record",
                        out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<record>元素";
                        return -1;
                    }

                    // 取得日志记录中声称的新记录路径。不能轻易相信这个路径。
                    string strNewRecPath = DomUtil.GetAttr(node, "recPath");

                    // 
                    string strOldRecord = "";
                    string strOldRecPath = "";

                    string strOldItemBarcode = "";
                    string strNewItemBarcode = "";


                    string strExistXml = "";
                    byte[] exist_timestamp = null;


                    // 日志记录中记载的旧记录体
                    strOldRecord = DomUtil.GetElementText(domLog.DocumentElement,
                        "oldRecord",
                        out node);
                    if (node == null)
                    {
                        if (strAction == "change")
                        {
                            strError = "日志记录中缺<oldRecord>元素";
                            return -1;
                        }
                    }

                    // 日志记录中声称的旧记录路径。不能轻易相信这个路径。
                    if (node != null)
                        strOldRecPath = DomUtil.GetAttr(node, "recPath");


                    // 从日志记录中记载的旧记录体中,获得旧记录册条码号
                    if (String.IsNullOrEmpty(strOldRecord) == false)
                    {
                        nRet = GetItemBarcode(strOldRecord,
                            out strOldItemBarcode,
                            out strError);
                    }

                    nRet = GetItemBarcode(strRecord,
                        out strNewItemBarcode,
                        out strError);

                    // TODO: 需要检查新旧记录中,<barcode>是否一致?如果不一致,则需要对新条码号进行查重?
                    if (strAction == "new" && strOldItemBarcode == "")
                    {
                        if (String.IsNullOrEmpty(strNewItemBarcode) == true)
                        {
                            strError = "因为拟新创建的记录内容中没有包含册条码号,所以new操作被放弃";
                            return -1;
                        }

                        strOldItemBarcode = strNewItemBarcode;
                    }


                    // 如果有旧记录的册条码号,则需要从数据库中提取最新鲜的旧记录
                    // (如果没有旧记录的册条码号,则依日志记录中的旧记录)
                    if (String.IsNullOrEmpty(strOldItemBarcode) == false)
                    {
                        string strOutputItemRecPath = "";

                        // 从册条码号获得册记录
                        List<string> aPath = null;

                        // 获得册记录
                        // return:
                        //      -1  error
                        //      0   not found
                        //      1   命中1条
                        //      >1  命中多于1条
                        nRet = this.GetItemRecXml(
                            // Channels,
                            channel,
                            strOldItemBarcode,
                            out strExistXml,
                            100,
                            out aPath,
                            out exist_timestamp,
                            out strError);
                        if (nRet == 0 || nRet == -1)
                        {
                            if (strAction == "change")
                            {
                                /*
                                // 从库中没有找到,只好依日志记录中记载的旧记录
                                strExistXml = strOldRecord;
                                 * */
                                strExistXml = "";

                                // 需要创建一条新记录。strOldRecPath中的路径似乎也可以用,但是要严格检查这个路径是否已经存在记录 -- 只能在这里位置不存在记录时才能用。既然如此麻烦,那就不如纯粹用一个新位置
                                strOutputItemRecPath = ResPath.GetDbName(strOldRecPath) + "/?";
                            }
                            else
                            {
                                Debug.Assert(strAction == "new", "");
                                strExistXml = "";
                                strOutputItemRecPath = ResPath.GetDbName(strNewRecPath) + "/?";
                            }
                        }
                        else
                        {
                            // 找到一条或者多条旧记录
                            Debug.Assert(aPath != null && aPath.Count >= 1, "");

                            bool bNeedReload = false;

                            if (aPath.Count == 1)
                            {
                                Debug.Assert(nRet == 1, "");

                                strOutputItemRecPath = aPath[0];

                                // 是否需要重新装载?
                                bNeedReload = false;    // 所取得的第一个路径,其记录已经装载
                            }
                            else
                            {
                                // 多条
                                Debug.Assert(aPath.Count > 1, "");

                                ///
                                // 建议根据strOldRecPath来进行挑选
                                if (String.IsNullOrEmpty(strOldRecPath) == true)
                                {
                                    // 空,无法挑选

                                    // 容错!
                                    strOutputItemRecPath = aPath[0];

                                    // 是否需要重新装载?
                                    bNeedReload = false;    // 所取得的第一个路径,其记录已经装载
                                }
                                else
                                {

                                    ///// 
                                    nRet = aPath.IndexOf(strOldRecPath);
                                    if (nRet != -1)
                                    {
                                        // 选中
                                        strOutputItemRecPath = aPath[nRet];

                                        // 是否需要重新装载?
                                        if (nRet != 0)
                                            bNeedReload = true; // 第一个以外的路径才需要装载

                                    }
                                    else
                                    {
                                        // 没有选中,只好依第一个

                                        // 容错
                                        strOutputItemRecPath = aPath[0];

                                        // 是否需要重新装载?
                                        bNeedReload = false;    // 所取得的第一个路径,其记录已经装载
                                    }
                                }

                                ///

                            }

                            // 重新装载
                            if (bNeedReload == true)
                            {
                                string strMetaData = "";
                                lRet = channel.GetRes(strOutputItemRecPath,
                                    out strExistXml,
                                    out strMetaData,
                                    out exist_timestamp,
                                    out strOutputItemRecPath,
                                    out strError);
                                if (lRet == -1)
                                {
                                    strError = "根据strOutputItemRecPath '" + strOutputItemRecPath + "' 重新获得册记录失败: " + strError;
                                    return -1;
                                }

                                // 需要检查记录中的<barcode>元素值是否匹配册条码号

                            }

                        }

                        // 修正strOldRecPath
                        if (strOutputItemRecPath != "")
                            strOldRecPath = strOutputItemRecPath;
                        else
                            strOldRecPath = ""; // 破坏掉,以免后面被用

                        strNewRecPath = strOutputItemRecPath;

                    } // end if 如果有旧记录的册条码号
                    else
                    {
                        // (如果没有旧记录的册条码号,则依日志记录中的旧记录)
                        // 但无法确定旧记录的路径。也就无法确定覆盖位置。因此建议放弃这种特定的“修改操作”。
                        strError = "因为日志记录中没有记载旧记录条码号,因此无法确定记录位置,因此change操作被放弃";
                        return -1;
                    }

                    if (strAction == "change")
                    {
                        if (strNewItemBarcode != ""
                            && strNewItemBarcode != strOldItemBarcode)
                        {
                            // 新旧记录的条码号不一致,需要对新条码号进行查重
                            List<string> aPath = null;

                            string strTempXml = "";
                            byte[] temp_timestamp = null;
                            // 获得册记录
                            // return:
                            //      -1  error
                            //      0   not found
                            //      1   命中1条
                            //      >1  命中多于1条
                            nRet = this.GetItemRecXml(
                                // Channels,
                                channel,
                                strNewItemBarcode,
                                out strTempXml,
                                100,
                                out aPath,
                                out temp_timestamp,
                                out strError);
                            if (nRet > 0)
                            {
                                // 有重复,取其第一条,作为老记录进行合并,并保存回这条的位置
                                strNewRecPath = aPath[0];
                                exist_timestamp = temp_timestamp;
                                strExistXml = strTempXml;
                            }
                        }
                    }


                    // 把两个记录装入DOM
                    XmlDocument domExist = new XmlDocument();
                    XmlDocument domNew = new XmlDocument();

                    try
                    {
                        // 防范空记录
                        if (String.IsNullOrEmpty(strExistXml) == true)
                            strExistXml = "<root />";

                        domExist.LoadXml(strExistXml);
                    }
                    catch (Exception ex)
                    {
                        strError = "strExistXml装载进入DOM时发生错误: " + ex.Message;
                        goto ERROR1;
                    }

                    try
                    {
                        domNew.LoadXml(strRecord);
                    }
                    catch (Exception ex)
                    {
                        strError = "strRecord装载进入DOM时发生错误: " + ex.Message;
                        goto ERROR1;
                    }




                    // 合并新旧记录
                    string strNewXml = "";

                    if (bForce == false)
                    {
                        nRet = MergeTwoEntityXml(domExist,
                            domNew,
                            out strNewXml,
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;
                    }
                    else
                    {
                        strNewXml = domNew.OuterXml;
                    }

                    // 保存新记录
                    byte[] output_timestamp = null;

                    string strOutputPath = "";

                    if (strAction == "move")
                    {
                        // 复制源记录到目标位置,然后自动删除源记录
                        // 但是尚未在目标位置写入最新内容
                        lRet = channel.DoCopyRecord(strOldRecPath,
                            strNewRecPath,
                            true,   // bDeleteSourceRecord
                            out output_timestamp,
                            out strOutputPath,
                            out strError);
                        if (lRet == -1)
                            goto ERROR1;

                        exist_timestamp = output_timestamp; // 及时更新时间戳
                    }

                    /*
                    // 测试
                    {
                        string strRecID = ResPath.GetRecordId(strNewRecPath);

                        if (strRecID != "?")
                        {
                            try
                            {
                                long id = Convert.ToInt64(strRecID);
                                if (id > 150848)
                                {
                                    Debug.Assert(false, "id超过尾部");
                                }
                            }
                            catch
                            {
                            }
                        }
                    }
                     * */

                    lRet = channel.DoSaveTextRes(strNewRecPath,
                        strNewXml,
                        false,   // include preamble?
                        "content,ignorechecktimestamp",
                        exist_timestamp,
                        out output_timestamp,
                        out strOutputPath,
                        out strError);
                    if (lRet == -1)
                        goto ERROR1;


                }
                else if (strAction == "delete")
                {
                    XmlNode node = null;
                    string strOldRecord = DomUtil.GetElementText(domLog.DocumentElement,
                        "oldRecord",
                        out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<oldRecord>元素";
                        return -1;
                    }
                    string strRecPath = DomUtil.GetAttr(node, "recPath");

                    string strOldItemBarcode = "";
                    nRet = GetItemBarcode(strOldRecord,
                        out strOldItemBarcode,
                        out strError);
                    if (String.IsNullOrEmpty(strOldItemBarcode) == true)
                    {
                        strError = "因为日志记录中的旧记录中缺乏非空的<barcode>内容,所以无法进行依据条码号定位的删除,delete操作被放弃";
                        return -1;
                    }

                    string strOutputItemRecPath = "";
                    string strExistXml = "";
                    byte[] exist_timestamp = null;

                    // 从册条码号获得册记录
                    List<string> aPath = null;

                    // 获得册记录
                    // return:
                    //      -1  error
                    //      0   not found
                    //      1   命中1条
                    //      >1  命中多于1条
                    nRet = this.GetItemRecXml(
                        // Channels,
                        channel,
                        strOldItemBarcode,
                        out strExistXml,
                        100,
                        out aPath,
                        out exist_timestamp,
                        out strError);
                    if (nRet == -1)
                        return -1;
                    if (nRet == 0)
                    {
                        // 本来就不存在
                        return 0;
                    }
                    if (nRet >= 1)
                    {
                        ///
                        // 找到一条或者多条旧记录
                        Debug.Assert(aPath != null && aPath.Count >= 1, "");

                        bool bNeedReload = false;

                        if (aPath.Count == 1)
                        {
                            Debug.Assert(nRet == 1, "");

                            /*
                            strOutputItemRecPath = aPath[0];

                            // 是否需要重新装载?
                            bNeedReload = false;    // 所取得的第一个路径,其记录已经装载
                             * */
                            strError = "册条码号 " + strOldItemBarcode + " 目前仅有唯一一条记录,放弃删除";
                            return -1;
                        }
                        else
                        {
                            // 多条
                            Debug.Assert(aPath.Count > 1, "");

                            ///
                            // 建议根据strRecPath来进行挑选
                            if (String.IsNullOrEmpty(strRecPath) == true)
                            {
                                strError = "册条码号 '" + strOldItemBarcode + "' 命中 " + aPath.Count.ToString() + " 条记录,而<oldRecord>的recPath参数缺乏,因此无法进行精确删除,delete操作被放弃";
                                return -1;
                            }
                            else
                            {

                                ///// 
                                nRet = aPath.IndexOf(strRecPath);
                                if (nRet != -1)
                                {
                                    // 选中
                                    strOutputItemRecPath = aPath[nRet];

                                    // 是否需要重新装载?
                                    if (nRet != 0)
                                        bNeedReload = true; // 第一个以外的路径才需要装载

                                }
                                else
                                {
                                    strError = "册条码号 '" + strOldItemBarcode + "' 命中 " + aPath.Count.ToString() + " 条记录,虽用了(<oldRecord>元素中属性recPath的)确认路径 '" + strRecPath + "' 也无法确认出其中一条,无法精确删除,因此delete操作被放弃";
                                    return -1;
                                }
                            }



                        }

                        ///

                        // 重新装载
                        if (bNeedReload == true)
                        {
                            string strMetaData = "";
                            lRet = channel.GetRes(strOutputItemRecPath,
                                out strExistXml,
                                out strMetaData,
                                out exist_timestamp,
                                out strOutputItemRecPath,
                                out strError);
                            if (lRet == -1)
                            {
                                strError = "根据strOutputItemRecPath '" + strOutputItemRecPath + "' 重新获得册记录失败: " + strError;
                                return -1;
                            }

                            // 需要检查记录中的<barcode>元素值是否匹配册条码号

                        }

                    }

                    // 把两个记录装入DOM
                    XmlDocument domExist = new XmlDocument();
                    try
                    {
                        // 防范空记录
                        if (String.IsNullOrEmpty(strExistXml) == true)
                            strExistXml = "<root />";

                        domExist.LoadXml(strExistXml);
                    }
                    catch (Exception ex)
                    {
                        strError = "strExistXml装载进入DOM时发生错误: " + ex.Message;
                        return -1;
                    }

                    string strDetail = "";
                    bool bHasCirculationInfo = IsEntityHasCirculationInfo(domExist,
                        out strDetail);


                    // 观察已经存在的记录是否有流通信息
                    if (bHasCirculationInfo == true
                        && bForce == false)
                    {
                        strError = "拟删除的册记录 '" + strOutputItemRecPath + "' 中包含有流通信息("+strDetail+"),不能删除。";
                        goto ERROR1;
                    }

                    int nRedoCount = 0;
                    byte[] timestamp = exist_timestamp;
                    byte[] output_timestamp = null; 

                REDO:
                    // 删除册记录
                    lRet = channel.DoDeleteRes(strOutputItemRecPath,
                        timestamp,
                        out output_timestamp,
                        out strError);
                    if (lRet == -1)
                    {
                        if (channel.ErrorCode == ChannelErrorCode.NotFound)
                            return 0;   // 记录本来就不存在
                        if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch)
                        {
                            if (nRedoCount < 10)
                            {
                                timestamp = output_timestamp;
                                nRedoCount++;
                                goto REDO;
                            }
                        }
                        strError = "删除册记录 '" + strRecPath + "' 时发生错误: " + strError;
                        return -1;

                    }
                }
                else
                {
                    strError = "无法识别的<action>内容 '" + strAction + "'";
                    return -1;
                }
            }

            return 0;
        ERROR1:
            if (level == RecoverLevel.LogicAndSnapshot)
            {
                level = RecoverLevel.Snapshot;
                goto DO_SNAPSHOT;
            }
            return -1;
        }
예제 #19
0
        /*
<root>
<operation>writeRes</operation> 
<requestResPath>...</requestResPath> 资源路径参数。也就是请求API是的strResPath参数值。可能在路径中的记录ID部分包含问号,表示要追加创建新的记录
<resPath>...</resPath> 资源路径。资源的确定路径。
<ranges>...</ranges> 字节范围
<totalLength>...</totalLength> 总长度
<metadata>...</metadata> 此元素的文本即是记录体,但注意为不透明的字符串(HtmlEncoding后的记录字符串)。
<style>...</style> 当 style 中包含 delete 子串时表示要删除这个资源 
<operator>test</operator> 
<operTime>Fri, 08 Dec 2006 10:12:20 GMT</operTime> 
</root>
         * 可能会有一个attachment
 * * */
        public int RecoverWriteRes(
            RmsChannelCollection Channels,
            RecoverLevel level,
            XmlDocument domLog,
            Stream attachmentLog,
            out string strError)
        {
            strError = "";

            // 暂时把Robust当作Logic处理
            if (level == RecoverLevel.Robust)
                level = RecoverLevel.Logic;

            long lRet = 0;
            // int nRet = 0;

            RmsChannel channel = Channels.GetChannel(this.WsUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }

            bool bReuse = false;    // 是否能够不顾RecorverLevel状态而重用部分代码

        DO_SNAPSHOT:

            // 快照恢复
            if (level == RecoverLevel.Snapshot
                || bReuse == true)
            {
                string strResPath = DomUtil.GetElementText(
                    domLog.DocumentElement,
                    "resPath");
                if (string.IsNullOrEmpty(strResPath) == true)
                {
                    strError = "日志记录中缺<resPath>元素";
                    return -1;
                }

                string strRanges = DomUtil.GetElementText(
    domLog.DocumentElement,
    "ranges");
                if (string.IsNullOrEmpty(strRanges) == true)
                {
                    strError = "日志记录中缺<ranges>元素";
                    return -1;
                }

                string strTotalLength = DomUtil.GetElementText(
domLog.DocumentElement,
"totalLength");
                if (string.IsNullOrEmpty(strTotalLength) == true)
                {
                    strError = "日志记录中缺<totalLength>元素";
                    return -1;
                }

                long lTotalLength = 0;
                try
                {
                    lTotalLength = Convert.ToInt64(strTotalLength);
                }
                catch
                {
                    strError = "lTotalLength值 '"+strTotalLength+"' 格式不正确";
                    return -1;
                }
                string strMetadata = DomUtil.GetElementText(
domLog.DocumentElement,
"metadata");
                string strStyle = DomUtil.GetElementText(
domLog.DocumentElement,
"style");

                // 读入记录内容
                byte[] baRecord = null;

                if (attachmentLog != null && attachmentLog.Length > 0)
                {
                    baRecord = new byte[(int)attachmentLog.Length];
                    attachmentLog.Seek(0, SeekOrigin.Begin);
                    attachmentLog.Read(baRecord, 0, (int)attachmentLog.Length);
                }

                strStyle += ",ignorechecktimestamp";

                byte[] timestamp = null;
                string strOutputResPath = "";
                byte[] output_timestamp = null;

                if (StringUtil.IsInList("delete", strStyle) == true)
                {
                    // 2015/9/3 增加
                    lRet = channel.DoDeleteRes(strResPath,
                        timestamp,
                        strStyle,
                        out output_timestamp,
                        out strError);
                }
                else
                {
                    lRet = channel.WriteRes(strResPath,
        strRanges,
        lTotalLength,
        baRecord,
        strMetadata,
        strStyle,
        timestamp,
        out strOutputResPath,
        out output_timestamp,
        out strError);
                }
                if (lRet == -1)
                {
                    strError = "WriteRes() '" + strResPath + "' 时发生错误: " + strError;
                    return -1;
                }

                return 0;
            }

            // 逻辑恢复或者混合恢复
            if (level == RecoverLevel.Logic
                || level == RecoverLevel.LogicAndSnapshot)
            {
                // 和SnapShot方式相同
                bReuse = true;
                goto DO_SNAPSHOT;
            }
            return 0;
        ERROR1:
            if (level == RecoverLevel.LogicAndSnapshot)
            {
                level = RecoverLevel.Snapshot;
                goto DO_SNAPSHOT;
            }
            return -1;
        }
예제 #20
0
        // SetComments() API 恢复动作
        /* 日志记录格式
<root>
  <operation>setComment</operation> 操作类型
  <action>new</action> 具体动作。有new change delete 3种
  <style>...</style> 风格。有force nocheckdup noeventlog 3种
  <record recPath='中文图书评注/3'>...</record> 记录体
  <oldRecord recPath='中文图书评注/3'>...</oldRecord> 被覆盖或者删除的记录 动作为change和delete时具备此元素
  <operator>test</operator> 操作者
  <operTime>Fri, 08 Dec 2006 08:41:46 GMT</operTime> 操作时间
</root>

注:1) 当<action>为delete时,没有<record>元素。为new时,没有<oldRecord>元素。
	2) 一次SetComments()API调用, 可能创建多条日志记录。
         
         * */
        // TODO: 要兑现style中force nocheckdup功能
        public int RecoverSetComment(
            RmsChannelCollection Channels,
            RecoverLevel level,
            XmlDocument domLog,
            out string strError)
        {
            strError = "";

            long lRet = 0;
            int nRet = 0;

            RmsChannel channel = Channels.GetChannel(this.WsUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }

            bool bReuse = false;    // 是否能够不顾RecorverLevel状态而重用部分代码

        DO_SNAPSHOT:

            string strAction = DomUtil.GetElementText(domLog.DocumentElement,
                "action");

            // 快照恢复
            if (level == RecoverLevel.Snapshot
                || bReuse == true)
            {

                byte[] timestamp = null;
                byte[] output_timestamp = null;
                string strOutputPath = "";

                if (strAction == "new"
                    || strAction == "change"
                    || strAction == "move")
                {
                    XmlNode node = null;
                    string strRecord = DomUtil.GetElementText(domLog.DocumentElement,
                        "record",
                        out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<record>元素";
                        return -1;
                    }

                    string strNewRecPath = DomUtil.GetAttr(node, "recPath");

                    // 
                    string strOldRecord = "";
                    string strOldRecPath = "";
                    if (strAction == "move")
                    {
                        strOldRecord = DomUtil.GetElementText(domLog.DocumentElement,
                            "oldRecord",
                            out node);
                        if (node == null)
                        {
                            strError = "日志记录中缺<oldRecord>元素";
                            return -1;
                        }

                        strOldRecPath = DomUtil.GetAttr(node, "recPath");
                    }

                    // 写评注记录
                    lRet = channel.DoSaveTextRes(strNewRecPath,
                        strRecord,
                        false,
                        "content,ignorechecktimestamp",
                        timestamp,
                        out output_timestamp,
                        out strOutputPath,
                        out strError);
                    if (lRet == -1)
                    {
                        strError = "写入评注记录 '" + strNewRecPath + "' 时发生错误: " + strError;
                        return -1;
                    }

                    if (strAction == "move")
                    {
                        // 删除评注记录
                        int nRedoCount = 0;

                    REDO_DELETE:
                        lRet = channel.DoDeleteRes(strOldRecPath,
                            timestamp,
                            out output_timestamp,
                            out strError);
                        if (lRet == -1)
                        {
                            if (channel.ErrorCode == ChannelErrorCode.NotFound)
                                return 0;   // 记录本来就不存在

                            if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch)
                            {
                                if (nRedoCount < 10)
                                {
                                    timestamp = output_timestamp;
                                    nRedoCount++;
                                    goto REDO_DELETE;
                                }
                            }
                            strError = "删除评注记录 '" + strOldRecPath + "' 时发生错误: " + strError;
                            return -1;

                        }
                    }

                }
                else if (strAction == "delete")
                {
                    XmlNode node = null;
                    string strOldRecord = DomUtil.GetElementText(domLog.DocumentElement,
                        "oldRecord",
                        out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<oldRecord>元素";
                        return -1;
                    }
                    string strRecPath = DomUtil.GetAttr(node, "recPath");

                    int nRedoCount = 0;
                REDO:
                    // 删除评注记录
                    lRet = channel.DoDeleteRes(strRecPath,
                        timestamp,
                        out output_timestamp,
                        out strError);
                    if (lRet == -1)
                    {
                        if (channel.ErrorCode == ChannelErrorCode.NotFound)
                            return 0;   // 记录本来就不存在
                        if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch)
                        {
                            if (nRedoCount < 10)
                            {
                                timestamp = output_timestamp;
                                nRedoCount++;
                                goto REDO;
                            }
                        }
                        strError = "删除评注记录 '" + strRecPath + "' 时发生错误: " + strError;
                        return -1;
                    }
                }
                else
                {
                    strError = "无法识别的<action>内容 '" + strAction + "'";
                    return -1;
                }


                return 0;
            }

            bool bForce = false;
            bool bNoCheckDup = false;

            string strStyle = DomUtil.GetElementText(domLog.DocumentElement,
                "style");

            if (StringUtil.IsInList("force", strStyle) == true)
                bForce = true;

            if (StringUtil.IsInList("nocheckdup", strStyle) == true)
                bNoCheckDup = true;

            // 逻辑恢复或者混合恢复或者容错恢复
            if (level == RecoverLevel.Logic
                || level == RecoverLevel.LogicAndSnapshot
                || level == RecoverLevel.Robust)    // 容错恢复没有单独实现
            {
                // 和数据库中已有记录合并,然后保存
                if (strAction == "new"
                    || strAction == "change"
                    || strAction == "move")
                {
                    XmlNode node = null;
                    string strRecord = DomUtil.GetElementText(domLog.DocumentElement,
                        "record",
                        out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<record>元素";
                        return -1;
                    }

                    string strNewRecPath = DomUtil.GetAttr(node, "recPath");

                    // 
                    string strOldRecord = "";
                    string strOldRecPath = "";
                    if (strAction == "move")
                    {
                        strOldRecord = DomUtil.GetElementText(domLog.DocumentElement,
                            "oldRecord",
                            out node);
                        if (node == null)
                        {
                            strError = "日志记录中缺<oldRecord>元素";
                            return -1;
                        }

                        strOldRecPath = DomUtil.GetAttr(node, "recPath");
                    }


                    // 读出数据库中原有的记录
                    string strExistXml = "";
                    string strMetaData = "";
                    byte[] exist_timestamp = null;
                    string strOutputPath = "";

                    if ((strAction == "change"
                        || strAction == "move")
                        && bForce == false)
                    {
                        string strSourceRecPath = "";

                        if (strAction == "change")
                            strSourceRecPath = strNewRecPath;
                        if (strAction == "move")
                            strSourceRecPath = strOldRecPath;

                        lRet = channel.GetRes(strSourceRecPath,
                            out strExistXml,
                            out strMetaData,
                            out exist_timestamp,
                            out strOutputPath,
                            out strError);
                        if (lRet == -1)
                        {
                            // 容错
                            if (channel.ErrorCode == ChannelErrorCode.NotFound
                                && level == RecoverLevel.LogicAndSnapshot)
                            {
                                // 如果记录不存在, 则构造一条空的记录
                                // bExist = false;
                                strExistXml = "<root />";
                                exist_timestamp = null;
                            }
                            else
                            {
                                strError = "在读入原有记录 '" + strNewRecPath + "' 时失败: " + strError;
                                goto ERROR1;
                            }
                        }
                    }

                    //
                    // 把两个记录装入DOM

                    XmlDocument domExist = new XmlDocument();
                    XmlDocument domNew = new XmlDocument();

                    try
                    {
                        // 防范空记录
                        if (String.IsNullOrEmpty(strExistXml) == true)
                            strExistXml = "<root />";

                        domExist.LoadXml(strExistXml);
                    }
                    catch (Exception ex)
                    {
                        strError = "strExistXml装载进入DOM时发生错误: " + ex.Message;
                        goto ERROR1;
                    }

                    try
                    {
                        domNew.LoadXml(strRecord);
                    }
                    catch (Exception ex)
                    {
                        strError = "strRecord装载进入DOM时发生错误: " + ex.Message;
                        goto ERROR1;
                    }

                    // 合并新旧记录
                    string strNewXml = "";

                    if (bForce == false)
                    {
                        nRet = this.CommentItemDatabase.MergeTwoItemXml(
                            null,
                            domExist,
                            domNew,
                            out strNewXml,
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;
                    }
                    else
                    {
                        strNewXml = domNew.OuterXml;
                    }

                    // 保存新记录
                    byte[] output_timestamp = null;

                    if (strAction == "move")
                    {
                        // 复制源记录到目标位置,然后自动删除源记录
                        // 但是尚未在目标位置写入最新内容
                        lRet = channel.DoCopyRecord(strOldRecPath,
                            strNewRecPath,
                            true,   // bDeleteSourceRecord
                            out output_timestamp,
                            out strOutputPath,
                            out strError);
                        if (lRet == -1)
                            goto ERROR1;

                        exist_timestamp = output_timestamp; // 及时更新时间戳
                    }


                    lRet = channel.DoSaveTextRes(strNewRecPath,
                        strNewXml,
                        false,   // include preamble?
                        "content,ignorechecktimestamp",
                        exist_timestamp,
                        out output_timestamp,
                        out strOutputPath,
                        out strError);
                    if (lRet == -1)
                        goto ERROR1;
                }
                else if (strAction == "delete")
                {
                    // 和SnapShot方式相同
                    bReuse = true;
                    goto DO_SNAPSHOT;
                }
                else
                {
                    strError = "无法识别的<action>内容 '" + strAction + "'";
                    return -1;
                }
            }

            return 0;
        ERROR1:
            if (level == RecoverLevel.LogicAndSnapshot)
            {
                level = RecoverLevel.Snapshot;
                goto DO_SNAPSHOT;
            }
            return -1;
        }
예제 #21
0
        // 删除应用服务器在dp2Kernel内核中创建的数据库
        // parameters:
        //      strXmlFileName  library.xml 文件的全路径
        // return:
        //      -1  出错
        //      0   用户放弃删除
        //      1   已经删除
        public static int DeleteKernelDatabases(
            IWin32Window owner,
            string strInstanceName,
            string strXmlFilename,
            out string strError)
        {
            strError = "";
            int nRet = 0;

            DialogResult result = MessageBox.Show(owner == null ? ForegroundWindow.Instance : owner,
                "是否要删除应用服务器实例 '" + strInstanceName + "' 在数据库内核中创建过的全部数据库?\r\n\r\n(注:如果现在不删除,将来也可以用内核管理(dp2manager)工具进行删除)",
                "安装 dp2Library",
                MessageBoxButtons.YesNo,
                MessageBoxIcon.Question,
                MessageBoxDefaultButton.Button1);
            if (result == DialogResult.No)
                return 0;

            XmlDocument dom = new XmlDocument();
            try
            {
                dom.Load(strXmlFilename);
            }
            catch (Exception ex)
            {
                strError = "XML文件 '" + strXmlFilename + "' 装载到DOM时发生错误: " + ex.Message;
                return -1;
            }

            XmlNode rmsserver_node = dom.DocumentElement.SelectSingleNode("rmsserver");
            if (rmsserver_node == null)
            {
                strError = "<rmsserver>元素没有找到";
                return -1;
            }
            string strKernelUrl = DomUtil.GetAttr(rmsserver_node, "url");
            if (String.IsNullOrEmpty(strKernelUrl) == true)
            {
                strError = "<rmsserver>元素的url属性为空";
                return -1;
            }

            using (RmsChannelCollection channels = new RmsChannelCollection())
            {
                RmsChannel channel = channels.GetChannel(strKernelUrl);
                if (channel == null)
                {
                    strError = "channel == null";
                    return -1;
                }

                string strUserName = DomUtil.GetAttr(rmsserver_node, "username");
                string strPassword = DomUtil.GetAttr(rmsserver_node, "password");

                string EncryptKey = "dp2circulationpassword";
                try
                {
                    strPassword = Cryptography.Decrypt(
                        strPassword,
                        EncryptKey);
                }
                catch
                {
                    strError = "<rmsserver>元素password属性中的密码设置不正确";
                    return -1;
                }


                nRet = channel.Login(strUserName,
                    strPassword,
                    out strError);
                if (nRet == -1)
                {
                    strError = "以用户名 '" + strUserName + "' 和密码登录内核时失败: " + strError;
                    return -1;
                }

                nRet = DeleteAllDatabase(
                    channel,
                    dom,
                    out strError);
                if (nRet == -1)
                    return -1;

                return 1;
            }
        }
예제 #22
0
        // ChangeReaderPassword() API 恢复动作
        /*
<root>
  <operation>changeReaderPassword</operation> 
  <readerBarcode>...</readerBarcode>	读者证条码号
  <newPassword>5npAUJ67/y3aOvdC0r+Dj7SeXGE=</newPassword> 
  <operator>test</operator> 
  <operTime>Fri, 08 Dec 2006 09:01:38 GMT</operTime> 
  <readerRecord recPath='...'>...</readerRecord>	最新读者记录
</root>
         * */
        public int RecoverChangeReaderPassword(
            RmsChannelCollection Channels,
            RecoverLevel level,
            XmlDocument domLog,
            out string strError)
        {
            strError = "";

            // 暂时把Robust当作Logic处理
            if (level == RecoverLevel.Robust)
                level = RecoverLevel.Logic;


            long lRet = 0;
            int nRet = 0;

            RmsChannel channel = Channels.GetChannel(this.WsUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }

            DO_SNAPSHOT:

            // 快照恢复
            if (level == RecoverLevel.Snapshot)
            {
                XmlNode node = null;
                string strReaderXml = DomUtil.GetElementText(domLog.DocumentElement,
                    "readerRecord",
                    out node);
                if (node == null)
                {
                    strError = "日志记录中缺<readerRecord>元素";
                    return -1;
                }
                string strReaderRecPath = DomUtil.GetAttr(node, "recPath");

                byte[] timestamp = null;
                byte[] output_timestamp = null;
                string strOutputPath = "";

                // 写读者记录
                lRet = channel.DoSaveTextRes(strReaderRecPath,
    strReaderXml,
    false,
    "content,ignorechecktimestamp",
    timestamp,
    out output_timestamp,
    out strOutputPath,
    out strError);
                if (lRet == -1)
                {
                    strError = "写入读者记录 '" + strReaderRecPath + "' 时发生错误: " + strError;
                    return -1;
                }

                return 0;
            }

            // 逻辑恢复或者混合恢复
            if (level == RecoverLevel.Logic
                || level == RecoverLevel.LogicAndSnapshot)
            {

                // 读出原有读者记录,修改密码后存回
                string strReaderBarcode = DomUtil.GetElementText(domLog.DocumentElement,
                    "readerBarcode");
                if (String.IsNullOrEmpty(strReaderBarcode) == true)
                {
                    strError = "日志记录中缺乏<readerBarcode>元素";
                    goto ERROR1;
                }

                string strNewPassword = DomUtil.GetElementText(domLog.DocumentElement,
                    "newPassword");
                if (String.IsNullOrEmpty(strNewPassword) == true)
                {
                    strError = "日志记录中缺乏<newPassword>元素";
                    goto ERROR1;
                }

                // 读入读者记录
                string strReaderXml = "";
                string strOutputReaderRecPath = "";
                byte[] reader_timestamp = null;

                nRet = this.GetReaderRecXml(
                    // Channels,
                    channel,
                    strReaderBarcode,
                    out strReaderXml,
                    out strOutputReaderRecPath,
                    out reader_timestamp,
                    out strError);
                if (nRet == 0)
                {
                    strError = "读者证条码号 '" + strReaderBarcode + "' 不存在";
                    goto ERROR1;
                }
                if (nRet == -1)
                {
                    strError = "读入证条码号为 '" + strReaderBarcode + "' 的读者记录时发生错误: " + strError;
                    goto ERROR1;
                }

                XmlDocument readerdom = null;
                nRet = LibraryApplication.LoadToDom(strReaderXml,
                    out readerdom,
                    out strError);
                if (nRet == -1)
                {
                    strError = "装载读者记录进入XML DOM时发生错误: " + strError;
                    goto ERROR1;
                }

                // strNewPassword中本来就是SHA1形态
                DomUtil.SetElementText(readerdom.DocumentElement,
                    "password", strNewPassword);

                byte[] output_timestamp = null;
                string strOutputPath = "";

                // 写回读者记录
                lRet = channel.DoSaveTextRes(strOutputReaderRecPath,
                    readerdom.OuterXml,
                    false,
                    "content,ignorechecktimestamp",
                    reader_timestamp,
                    out output_timestamp,
                    out strOutputPath,
                    out strError);
                if (lRet == -1)
                    goto ERROR1;
            }


            return 0;
        ERROR1:
            if (level == RecoverLevel.LogicAndSnapshot)
            {
                level = RecoverLevel.Snapshot;
                goto DO_SNAPSHOT;
            }
            return -1;
        }
예제 #23
0
        // 检测管理用户是否已经存在?
        // return:
        //       -1  出错
        //      0   不存在
        //      1   存在, 且密码一致
        //      2   存在, 但密码不一致
        int DetectManageUser(out string strError)
        {
            strError = "";
            if (this.textBox_kernelUrl.Text == "")
            {
                strError = "尚未指定dp2Kernel服务器URL";
                return -1;
            }

            if (this.textBox_manageUserName.Text == "")
            {
                strError = "尚未指定代理帐户的用户名";
                return -1;
            }

            if (this.textBox_managePassword.Text != this.textBox_confirmManagePassword.Text)
            {
                strError = "代理帐户 密码 和 再次输入密码 不一致。请重新输入。";
                return -1;
            }

            RmsChannelCollection channels = new RmsChannelCollection();

            RmsChannel channel = channels.GetChannel(this.textBox_kernelUrl.Text);
            if (channel == null)
            {
                strError = "channel == null";
                return -1;
            }

            // Debug.Assert(false, "");

            int nRet = channel.Login(this.textBox_manageUserName.Text,
                this.textBox_managePassword.Text,
                out strError);
            if (nRet == -1)
            {
                strError = "以用户名 '" + this.textBox_manageUserName.Text + "' 和密码登录失败: " + strError;
                return -1;
            }

            channel.DoLogout(out strError);

            if (nRet == 0)
            {
                channels.AskAccountInfo -= new AskAccountInfoEventHandle(channels_AskAccountInfo);
                channels.AskAccountInfo += new AskAccountInfoEventHandle(channels_AskAccountInfo);

                nRet = channel.UiLogin("为确认代理帐户是否存在, 请用root用户身份登录。",
                    "",
                    LoginStyle.None,
                    out strError);
                if (nRet == -1 || nRet == 0)
                {
                    strError = "以root用户身份登录失败: " + strError + "\r\n\r\n因此无法确定代理帐户是否存在";
                    return -1;
                }

                string strRecPath = "";
                string strXml = "";
                byte[] baTimeStamp = null;


                // 获得用户记录
                // return:
                //      -1  error
                //      0   not found
                //      >=1   检索命中的条数
                nRet = GetUserRecord(
                    channel,
                    this.textBox_manageUserName.Text,
                    out strRecPath,
                    out strXml,
                    out baTimeStamp,
                    out strError);
                if (nRet == -1)
                {
                    strError = "获取用户 '" + this.textBox_manageUserName.Text + "' 信息时发生错误: " + strError + "\r\n\r\n因此无法确定代理帐户是否存在。";
                    return -1;
                }

                if (nRet == 1)
                {
                    strError = "代理帐户 '" + this.textBox_manageUserName.Text + "' 已经存在, 但其密码和当前面板拟设置的密码不一致。";
                    return 2;
                }
                if (nRet >= 1)
                {
                    strError = "以 '" + this.textBox_manageUserName.Text + "' 为用户名 的用户记录存在多条,这是一个严重错误,请利用root身份启用dp2manager尽快修正此错误。";
                    return -1;
                }

                strError = "代理帐户 '" + this.textBox_manageUserName.Text + "' 不存在。";
                return 0;
            }

            strError = "代理帐户 '" + this.textBox_manageUserName.Text + "' 代理帐户经检验存在。";
            return 1;
        }
예제 #24
0
        // SetReaderInfo() API 恢复动作
        /*
<root>
	<operation>setReaderInfo</operation> 操作类型
	<action>...</action> 具体动作。有new change delete move 4种
	<record recPath='...'>...</record> 新记录
    <oldRecord recPath='...'>...</oldRecord> 被覆盖或者删除的记录 动作为 change 和 delete 时具备此元素
    <changedEntityRecord itemBarcode='...' recPath='...' oldBorrower='...' newBorrower='...' /> 若干个元素。表示连带发生修改的册记录
	<operator>test</operator> 操作者
	<operTime>Fri, 08 Dec 2006 09:01:38 GMT</operTime> 操作时间
</root>

注: new 的时候只有<record>元素,delete的时候只有<oldRecord>元素,change的时候两者都有

         * */
        public int RecoverSetReaderInfo(
            RmsChannelCollection Channels,
            RecoverLevel level_param,
            XmlDocument domLog,
            out string strError)
        {
            strError = "";

            string[] element_names = reader_element_names;

            RecoverLevel level = level_param;

            // 暂时把Robust当作Logic处理
            if (level == RecoverLevel.Robust)
                level = RecoverLevel.Logic;

            long lRet = 0;
            int nRet = 0;

            RmsChannel channel = Channels.GetChannel(this.WsUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }

            bool bReuse = false;    // 是否能够不顾RecorverLevel状态而重用部分代码

            DO_SNAPSHOT:

            string strAction = DomUtil.GetElementText(domLog.DocumentElement,
                "action");

            // 快照恢复
            if (level == RecoverLevel.Snapshot
                || bReuse == true)
            {
                byte[] timestamp = null;
                byte[] output_timestamp = null;
                string strOutputPath = "";

                if (strAction == "new"
                    || strAction == "change")
                {
                    XmlNode node = null;
                    string strRecord = DomUtil.GetElementText(domLog.DocumentElement,
                        "record",
                        out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<record>元素";
                        return -1;
                    }
                    string strRecPath = DomUtil.GetAttr(node, "recPath");

                    // 写读者记录
                    lRet = channel.DoSaveTextRes(strRecPath,
        strRecord,
        false,
        "content,ignorechecktimestamp",
        timestamp,
        out output_timestamp,
        out strOutputPath,
        out strError);
                    if (lRet == -1)
                    {
                        strError = "写入读者记录 '" + strRecPath + "' 时发生错误: " + strError;
                        return -1;
                    }

                    // 2015/9/11
                    XmlNodeList nodes = domLog.DocumentElement.SelectNodes("changedEntityRecord");
                    foreach(XmlElement item in nodes)
                    {
                        string strItemBarcode = item.GetAttribute("itemBarcode");
                        string strItemRecPath = item.GetAttribute("recPath");
                        string strOldReaderBarcode = item.GetAttribute("oldBorrower");
                        string strNewReaderBarcode = item.GetAttribute("newBorrower");

                        // 修改一条册记录,的 borrower 元素内容
                        // parameters:
                        //      -2  保存记录时出错
                        //      -1  一般性错误
                        //      0   成功
                        nRet = ChangeBorrower(
                            channel,
                            strItemBarcode,
                            strItemRecPath,
                            strOldReaderBarcode,
                            strNewReaderBarcode,
                            true,
                            out strError);
                        if (nRet == -1 || nRet == -2)
                        {
                            strError = "修改读者记录所关联的在借册记录时出错:" + strError;
                            return -1;
                        }
                    }
                }
                else if (strAction == "delete")
                {
                    XmlNode node = null;
                    string strOldRecord = DomUtil.GetElementText(domLog.DocumentElement,
                        "oldRecord",
                        out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<oldRecord>元素";
                        return -1;
                    }
                    string strRecPath = DomUtil.GetAttr(node, "recPath");

                    int nRedoCount = 0;
                REDO:
                    // 删除读者记录
                    lRet = channel.DoDeleteRes(strRecPath,
                        timestamp,
                        out output_timestamp,
                        out strError);
                    if (lRet == -1)
                    {
                        if (channel.ErrorCode == ChannelErrorCode.NotFound)
                            return 0;   // 记录本来就不存在
                        if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch)
                        {
                            if (nRedoCount < 10)
                            {
                                timestamp = output_timestamp;
                                nRedoCount++;
                                goto REDO;
                            }
                        }
                        strError = "删除读者记录 '" + strRecPath + "' 时发生错误: " + strError;
                        return -1;

                    }
                }
                else if (strAction == "move")
                {
                    XmlNode node = null;
                    string strRecord = DomUtil.GetElementText(domLog.DocumentElement,
    "record",
    out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<record>元素";
                        return -1;
                    }
                    string strRecPath = DomUtil.GetAttr(node, "recPath");
                    if (string.IsNullOrEmpty(strRecPath) == true)
                    {
                        strError = "日志记录中<record>元素内缺recPath属性值";
                        return -1;
                    }

                    string strOldRecord = DomUtil.GetElementText(domLog.DocumentElement,
                        "oldRecord",
                        out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<oldRecord>元素";
                        return -1;
                    }
                    string strOldRecPath = DomUtil.GetAttr(node, "recPath");
                    if (string.IsNullOrEmpty(strOldRecPath) == true)
                    {
                        strError = "日志记录中<oldRecord>元素内缺recPath属性值";
                        return -1;
                    }
                    /*
                    int nRedoCount = 0;
                REDO:
                     * */

                    // 移动读者记录
                    lRet = channel.DoCopyRecord(
                        strOldRecPath,
                        strRecPath,
                        true,
                        out output_timestamp,
                        out strOutputPath,
                        out strError);
                    if (lRet == -1)
                    {
                        // 源记录本来就不存在。进行容错处理
                        if (channel.ErrorCode == ChannelErrorCode.NotFound
                            && level_param == RecoverLevel.Robust)
                        {
                            // 优先用最新的记录内容复原。实在没有才用旧的记录内容
                            if (string.IsNullOrEmpty(strRecord) == true)
                                strRecord = strOldRecord;

                            if (string.IsNullOrEmpty(strRecord) == false)
                            {
                                // 写读者记录
                                lRet = channel.DoSaveTextRes(strRecPath,
                    strRecord,
                    false,
                    "content,ignorechecktimestamp",
                    timestamp,
                    out output_timestamp,
                    out strOutputPath,
                    out strError);
                                if (lRet == -1)
                                {
                                    strError = "为容错,写入读者记录 '" + strRecPath + "' 时发生错误: " + strError;
                                    return -1;
                                }

                                return 0;
                            }
                        }

                        strError = "移动读者记录 '" + strOldRecPath + "' 到 '" + strRecPath + "' 时发生错误: " + strError;
                        return -1;
                    }

                    // <record>中如果有记录体,则还需要写入一次
                    // 所以这里需要注意,在创建日志记录的时候,如果没有在CopyRecord()后追加修改过记录,则不要创建<record>记录正文部分,以免引起多余的日志恢复时写入动作
                    if (string.IsNullOrEmpty(strRecord) == false)
                    {
                        lRet = channel.DoSaveTextRes(strRecPath,
            strRecord,
            false,
            "content,ignorechecktimestamp",
            timestamp,
            out output_timestamp,
            out strOutputPath,
            out strError);
                        if (lRet == -1)
                        {
                            strError = "写入读者记录 '" + strRecPath + "' 时发生错误: " + strError;
                            return -1;
                        }
                    }
                }

                return 0;
            }

            // 逻辑恢复或者混合恢复
            if (level == RecoverLevel.Logic
                || level == RecoverLevel.LogicAndSnapshot)
            {
                // 和数据库中已有记录合并,然后保存
                if (strAction == "new" || strAction == "change")
                {
                    XmlNode node = null;
                    string strRecord = DomUtil.GetElementText(domLog.DocumentElement,
                        "record",
                        out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<record>元素";
                        return -1;
                    }

                    string strRecPath = DomUtil.GetAttr(node, "recPath");

                    // 读出数据库中原有的记录
                    string strExistXml = "";
                    string strMetaData = "";
                    byte[] exist_timestamp = null;
                    string strOutputPath = "";

                    if (strAction == "change")
                    {
                        lRet = channel.GetRes(strRecPath,
                            out strExistXml,
                            out strMetaData,
                            out exist_timestamp,
                            out strOutputPath,
                            out strError);
                        if (lRet == -1)
                        {
                            // 容错
                            if (channel.ErrorCode == ChannelErrorCode.NotFound
                                && level == RecoverLevel.LogicAndSnapshot)
                            {
                                // 如果记录不存在, 则构造一条空的记录
                                // bExist = false;
                                strExistXml = "<root />";
                                exist_timestamp = null;
                            }
                            else
                            {
                                strError = "在读入原有记录 '" + strRecPath + "' 时失败: " + strError;
                                goto ERROR1;
                            }
                        }
                    }

                    //
                    // 把两个记录装入DOM

                    XmlDocument domExist = new XmlDocument();
                    XmlDocument domNew = new XmlDocument();

                    try
                    {
                        // 防范空记录
                        if (String.IsNullOrEmpty(strExistXml) == true)
                            strExistXml = "<root />";

                        domExist.LoadXml(strExistXml);
                    }
                    catch (Exception ex)
                    {
                        strError = "strExistXml装载进入DOM时发生错误: " + ex.Message;
                        goto ERROR1;
                    }

                    try
                    {
                        domNew.LoadXml(strRecord);
                    }
                    catch (Exception ex)
                    {
                        strError = "strRecord装载进入DOM时发生错误: " + ex.Message;
                        goto ERROR1;
                    }

                    // 合并新旧记录
                    string strNewXml = "";
                    nRet = MergeTwoReaderXml(
                        element_names,
                        "change",
                        domExist,
                        domNew,
                        out strNewXml,
                        out strError);
                    if (nRet == -1)
                        goto ERROR1;

                    // 保存新记录
                    byte[] output_timestamp = null;
                    lRet = channel.DoSaveTextRes(strRecPath,
                        strNewXml,
                        false,   // include preamble?
                        "content,ignorechecktimestamp",
                        exist_timestamp,
                        out output_timestamp,
                        out strOutputPath,
                        out strError);
                    if (lRet == -1)
                    {
                        goto ERROR1;
                    }
                }
                else if (strAction == "delete")
                {
                    // 和SnapShot方式相同
                    bReuse = true;
                    goto DO_SNAPSHOT;
                }
                else if (strAction == "move")
                {
                    // 和SnapShot方式相同
                    bReuse = true;
                    goto DO_SNAPSHOT;
                }
                else
                {
                    strError = "无法识别的<action>内容 '" + strAction + "'";
                    return -1;
                }
            }

            return 0;
        ERROR1:
            if (level == RecoverLevel.LogicAndSnapshot)
            {
                level = RecoverLevel.Snapshot;
                goto DO_SNAPSHOT;
            }
            return -1;
        }
예제 #25
0
		// 检索文章
		// return:
		//		-1	error
		//		其他 命中数
		public int Search(
			string strServerUrl,
			string strQueryXml,
			RmsChannelCollection Channels,
			string strLang,
			out string strError)

		{
			strError = "";

			string strMessage = "";

			// 加写锁
			this.m_lock.AcquireWriterLock(m_nLockTimeout);
			try 
			{

				this.File.Clear();	// 清空集合


				//if (page.Response.IsClientConnected == false)	// 灵敏中断
				//	return -1;

				RmsChannel channel = Channels.GetChannel(strServerUrl);
				Debug.Assert(channel != null, "Channels.GetChannel 异常");

				strMessage += "--- begin search ...\r\n";

				DateTime time = DateTime.Now;

				//if (page.Response.IsClientConnected == false)	// 灵敏中断
				//	return -1;

				long nRet = channel.DoSearch(strQueryXml,
                    "default",
                    "", // strOuputStyle
					out strError);
				if (nRet == -1) 
				{
					strError = "检索时出错: " + strError;
					return -1;
				}


				TimeSpan delta = DateTime.Now - time;
				strMessage += "search end. time="+delta.ToString()+"\r\n";

				if (nRet == 0)
					return 0;	// not found

				long lTotalCount = nRet;

				//if (page.Response.IsClientConnected == false)	// 灵敏中断
				//	return -1;

				strMessage += "--- begin get search result ...\r\n";

				time = DateTime.Now;

				long lStart = 0;
				long lPerCount = Math.Min(lTotalCount, 1000);


				for(;;)
				{
					//if (page.Response.IsClientConnected == false)	// 灵敏中断
					//	return -1;


					List<string> aPath = null;
					lPerCount = Math.Min((lTotalCount - lStart), 1000);

					nRet = channel.DoGetSearchResult(
                        "default",
                        lStart,
						lPerCount,
						strLang,
						null,	// stop,
						out aPath,
						out strError);
					if (nRet == -1) 
					{
						strError = "检索库时出错: " + strError;
						return -1;
					}


					delta = DateTime.Now - time;
					strMessage += "get search result end. time="+delta.ToString()+"\r\n";


					if (aPath.Count == 0)
					{
						strError = "检索库时获取的检索结果为空";
						return -1;
					}

					//if (page.Response.IsClientConnected == false)	// 灵敏中断
					//	return -1;

					strMessage += "--- begin build storage ...\r\n";

					time = DateTime.Now;

					int i;
					// 加入新行对象。新行对象中,只初始化了m_strRecID参数
					for(i=0;i<aPath.Count;i++)
					{
						ClientRecordItem item = new ClientRecordItem();
						item.Path = (string)aPath[i];
						this.File.Add(item);

						if ((i % 100) == 0)
						{
							strMessage += "process " + Convert.ToString(i)+ "\r\n";
						}

					}

					delta = DateTime.Now - time;
					strMessage += "build storage end. time="+delta.ToString()+"\r\n";

					lStart += aPath.Count;
					if (lStart >= lTotalCount)
						break;

				}


				return 1;

			}
			finally
			{
				this.m_lock.ReleaseWriterLock();
			}
		}
예제 #26
0
        // Borrow() API 恢复动作
        /* 日志记录格式如下
<root>
  <operation>borrow</operation> 操作类型
  <readerBarcode>R0000002</readerBarcode> 读者证条码号
  <itemBarcode>0000001</itemBarcode>  册条码号
  <borrowDate>Fri, 08 Dec 2006 04:17:31 GMT</borrowDate> 借阅日期
  <borrowPeriod>30day</borrowPeriod> 借阅期限
  <no>0</no> 续借次数。0为首次普通借阅,1开始为续借
  <operator>test</operator> 操作者
  <operTime>Fri, 08 Dec 2006 04:17:31 GMT</operTime> 操作时间
  <confirmItemRecPath>...</confirmItemRecPath> 辅助判断用的册记录路径
  
  <readerRecord recPath='...'>...</readerRecord>	最新读者记录
  <itemRecord recPath='...'>...</itemRecord>	最新册记录
</root>
         * */
        // parameters:
        //      bForce  是否为容错状态。在容错状态下,如果遇到重复的册条码号,就算做第一条。
        public int RecoverBorrow(
            RmsChannelCollection Channels,
            RecoverLevel level,
            XmlDocument domLog,
            bool bForce,
            out string strError)
        {
            strError = "";

            long lRet = 0;
            int nRet = 0;

            RmsChannel channel = Channels.GetChannel(this.WsUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }

            DO_SNAPSHOT:

            // 快照恢复
            if (level == RecoverLevel.Snapshot)
            {
                XmlNode node = null;
                string strReaderXml = DomUtil.GetElementText(domLog.DocumentElement,
                    "readerRecord", 
                    out node);
                if (node == null)
                {
                    strError = "日志记录中缺<readerRecord>元素";
                    return -1;
                }
                string strReaderRecPath = DomUtil.GetAttr(node, "recPath");

                string strItemXml = DomUtil.GetElementText(domLog.DocumentElement,
    "itemRecord",
    out node);
                if (node == null)
                {
                    strError = "日志记录中缺<itemRecord>元素";
                    return -1;
                }
                string strItemRecPath = DomUtil.GetAttr(node, "recPath");

                byte[] timestamp = null;
                byte[] output_timestamp = null;
                string strOutputPath = "";

                // 写读者记录
                lRet = channel.DoSaveTextRes(strReaderRecPath,
    strReaderXml,
    false,
    "content,ignorechecktimestamp",
    timestamp,
    out output_timestamp,
    out strOutputPath,
    out strError);
                if (lRet == -1)
                {
                    strError = "写入读者记录 '" + strReaderRecPath + "' 时发生错误: " + strError;
                    return -1;
                }

                // 写册记录
                lRet = channel.DoSaveTextRes(strItemRecPath,
strItemXml,
false,
"content,ignorechecktimestamp",
timestamp,
out output_timestamp,
out strOutputPath,
out strError);
                if (lRet == -1)
                {
                    strError = "写入册记录 '" + strItemRecPath + "' 时发生错误: " + strError;
                    return -1;
                }

                return 0;
            }

            // 逻辑恢复或者混合恢复
            if (level == RecoverLevel.Logic
                || level == RecoverLevel.LogicAndSnapshot)
            {
                string strRecoverComment = "";

                string strReaderBarcode = DomUtil.GetElementText(domLog.DocumentElement,
                    "readerBarcode");
                if (String.IsNullOrEmpty(strReaderBarcode) == true)
                {
                    strError = "<readerBarcode>元素值为空";
                    goto ERROR1;
                }

                // 读入读者记录
                string strReaderXml = "";
                string strOutputReaderRecPath = "";
                byte[] reader_timestamp = null;

                nRet = this.GetReaderRecXml(
                    // Channels,
                    channel,
                    strReaderBarcode,
                    out strReaderXml,
                    out strOutputReaderRecPath,
                    out reader_timestamp,
                    out strError);
                if (nRet == 0)
                {
                    strError = "读者证条码号 '" + strReaderBarcode + "' 不存在";
                    goto ERROR1;
                }
                if (nRet == -1)
                {
                    strError = "读入证条码号为 '" + strReaderBarcode + "' 的读者记录时发生错误: " + strError;
                    goto ERROR1;
                }

                string strLibraryCode = "";
                // 获得读者库的馆代码
                // return:
                //      -1  出错
                //      0   成功
                nRet = GetLibraryCode(
                        strOutputReaderRecPath,
                        out strLibraryCode,
                        out strError);
                if (nRet == -1)
                    goto ERROR1;

                XmlDocument readerdom = null;
                nRet = LibraryApplication.LoadToDom(strReaderXml,
                    out readerdom,
                    out strError);
                if (nRet == -1)
                {
                    strError = "装载读者记录进入XML DOM时发生错误: " + strError;
                    goto ERROR1;
                }

                // 读入册记录
                string strConfirmItemRecPath = DomUtil.GetElementText(domLog.DocumentElement,
                    "confirmItemRecPath");
                string strItemBarcode = DomUtil.GetElementText(domLog.DocumentElement,
                    "itemBarcode");
                if (String.IsNullOrEmpty(strItemBarcode) == true)
                {
                    strError = "<strItemBarcode>元素值为空";
                    goto ERROR1;
                }

                string strItemXml = "";
                string strOutputItemRecPath = "";
                byte[] item_timestamp = null;

                // 如果已经有确定的册记录路径
                if (String.IsNullOrEmpty(strConfirmItemRecPath) == false)
                {
                    string strMetaData = "";
                    lRet = channel.GetRes(strConfirmItemRecPath,
                        out strItemXml,
                        out strMetaData,
                        out item_timestamp,
                        out strOutputItemRecPath,
                        out strError);
                    if (lRet == -1)
                    {
                        strError = "根据strConfirmItemRecPath '" + strConfirmItemRecPath + "' 获得册记录失败: " + strError;
                        goto ERROR1;
                    }

                    // 需要检查记录中的<barcode>元素值是否匹配册条码号


                    // TODO: 如果记录路径所表达的记录不存在,或者其<barcode>元素值和要求的册条码号不匹配,那么都要改用逻辑方法,也就是利用册条码号来获得记录。
                    // 当然,这种情况下,非常要紧的是确保数据库的素质很好,本身没有重条码号的情况出现。
                }
                else
                {
                    // 从册条码号获得册记录
                    List<string> aPath = null;

                    // 获得册记录
                    // return:
                    //      -1  error
                    //      0   not found
                    //      1   命中1条
                    //      >1  命中多于1条
                    nRet = this.GetItemRecXml(
                        // Channels,
                        channel,
                        strItemBarcode,
                        out strItemXml,
                        100,
                        out aPath,
                        out item_timestamp,
                        out strError);
                    if (nRet == 0)
                    {
                        strError = "册条码号 '" + strItemBarcode + "' 不存在";
                        goto ERROR1;
                    }
                    if (nRet == -1)
                    {
                        strError = "读入册条码号为 '" + strItemBarcode + "' 的册记录时发生错误: " + strError;
                        goto ERROR1;
                    }

                    if (aPath.Count > 1)
                    {
                        if (bForce == true)
                        {
                            // 容错!
                            strOutputItemRecPath = aPath[0];

                            strRecoverComment += "册条码号 " + strItemBarcode + " 有 "
                                + aPath.Count.ToString() + " 条重复记录,因受容错要求所迫,权且采用其中第一个记录 "
                                + strOutputItemRecPath + " 来进行借阅操作。";
                        }
                        else
                        {
                            strError = "册条码号为 '" + strItemBarcode + "' 的册记录有 " + aPath.Count.ToString() + " 条,但此时comfirmItemRecPath却为空";
                            goto ERROR1;
                        }
                    }
                    else
                    {

                        Debug.Assert(nRet == 1, "");
                        Debug.Assert(aPath.Count == 1, "");

                        if (nRet == 1)
                        {
                            strOutputItemRecPath = aPath[0];
                        }
                    }

                }

                XmlDocument itemdom = null;
                nRet = LibraryApplication.LoadToDom(strItemXml,
                    out itemdom,
                    out strError);
                if (nRet == -1)
                {
                    strError = "装载册记录进入XML DOM时发生错误: " + strError;
                    goto ERROR1;
                }

                // 修改读者记录
                // 修改册记录

                // TODO: 容错情况下如果遇到册条码号是重复的,要写入额外的日志。
                nRet = BorrowChangeReaderAndItemRecord(
                    // Channels,
                    channel,
                    strItemBarcode,
                    strReaderBarcode,
                    domLog,
                    strRecoverComment,
                    strLibraryCode,
                    ref readerdom,
                    ref itemdom,
                    out strError);
                if (nRet == -1)
                    goto ERROR1;

                // 写回读者、册记录
                byte[] output_timestamp = null;
                string strOutputPath = "";


                // 写回读者记录
                lRet = channel.DoSaveTextRes(strOutputReaderRecPath,
                    readerdom.OuterXml,
                    false,
                    "content,ignorechecktimestamp",
                    reader_timestamp,
                    out output_timestamp,
                    out strOutputPath,
                    out strError);
                if (lRet == -1)
                    goto ERROR1;

                // 写回册记录
                lRet = channel.DoSaveTextRes(strOutputItemRecPath,
                    itemdom.OuterXml,
                    false,
                    "content,ignorechecktimestamp",
                    item_timestamp,
                    out output_timestamp,
                    out strOutputPath,
                    out strError);
                if (lRet == -1)
                    goto ERROR1;

            }

            // 容错恢复
            if (level == RecoverLevel.Robust)
            {
                string strRecoverComment = "";

                string strReaderBarcode = DomUtil.GetElementText(domLog.DocumentElement,
                    "readerBarcode");
                if (String.IsNullOrEmpty(strReaderBarcode) == true)
                {
                    strError = "<readerBarcode>元素值为空";
                    return -1;
                }

                // 读入读者记录
                string strReaderXml = "";
                string strOutputReaderRecPath = "";
                byte[] reader_timestamp = null;

                nRet = this.GetReaderRecXml(
                    // Channels,
                    channel,
                    strReaderBarcode,
                    out strReaderXml,
                    out strOutputReaderRecPath,
                    out reader_timestamp,
                    out strError);
                if (nRet == 0)
                {
                    strError = "读者证条码号 '" + strReaderBarcode + "' 不存在";
                    // TODO: 记入信息文件

                    // 从日志记录中获得读者记录
                    XmlNode node = null;
                    strReaderXml = DomUtil.GetElementText(domLog.DocumentElement,
                        "readerRecord",
                        out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<readerRecord>元素";
                        return -1;
                    }
                    string strReaderRecPath = DomUtil.GetAttr(node, "recPath");
                    if (String.IsNullOrEmpty(strReaderRecPath) == true)
                    {
                        strError = "日志记录中<readerRecord>元素缺recPath属性";
                        return -1;
                    }

                    // 新增一条读者记录
                    strOutputReaderRecPath = ResPath.GetDbName(strReaderRecPath) + "/?";
                    reader_timestamp = null;
                }
                else
                {
                    if (nRet == -1)
                    {
                        strError = "读入证条码号为 '" + strReaderBarcode + "' 的读者记录时发生错误: " + strError;
                        return -1;
                    }
                }

                string strLibraryCode = "";
                // 获得读者库的馆代码
                // return:
                //      -1  出错
                //      0   成功
                nRet = GetLibraryCode(
                        strOutputReaderRecPath,
                        out strLibraryCode,
                        out strError);
                if (nRet == -1)
                    goto ERROR1;

                XmlDocument readerdom = null;
                nRet = LibraryApplication.LoadToDom(strReaderXml,
                    out readerdom,
                    out strError);
                if (nRet == -1)
                {
                    strError = "装载读者记录进入XML DOM时发生错误: " + strError;
                    return -1;
                }

                // 读入册记录
                string strConfirmItemRecPath = DomUtil.GetElementText(domLog.DocumentElement,
                    "confirmItemRecPath");
                string strItemBarcode = DomUtil.GetElementText(domLog.DocumentElement,
                    "itemBarcode");
                if (String.IsNullOrEmpty(strItemBarcode) == true)
                {
                    strError = "<strItemBarcode>元素值为空";
                    return -1;
                }

                string strItemXml = "";
                string strOutputItemRecPath = "";
                byte[] item_timestamp = null;


                // 从册条码号获得册记录
                List<string> aPath = null;

                // 获得册记录
                // return:
                //      -1  error
                //      0   not found
                //      1   命中1条
                //      >1  命中多于1条
                nRet = this.GetItemRecXml(
                    // Channels,
                    channel,
                    strItemBarcode,
                    out strItemXml,
                    100,
                    out aPath,
                    out item_timestamp,
                    out strError);
                if (nRet == 0)
                {
                    strError = "册条码号 '" + strItemBarcode + "' 不存在";
                    // TODO: 记入信息文件

                    XmlNode node = null;
                    strItemXml = DomUtil.GetElementText(domLog.DocumentElement,
                        "itemRecord",
                        out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<itemRecord>元素";
                        return -1;
                    }
                    string strItemRecPath = DomUtil.GetAttr(node, "recPath");
                    if (String.IsNullOrEmpty(strItemRecPath) == true)
                    {
                        strError = "日志记录中<itemRecord>元素缺recPath属性";
                        return -1;
                    }

                    // 新增一条册记录
                    strOutputItemRecPath = ResPath.GetDbName(strItemRecPath) + "/?";
                    item_timestamp = null;
                }
                else
                {

                    if (nRet == -1)
                    {
                        strError = "读入册条码号为 '" + strItemBarcode + "' 的册记录时发生错误: " + strError;
                        return -1;
                    }

                    Debug.Assert(aPath != null, "");

                    bool bNeedReload = false;

                    if (aPath.Count > 1)
                    {

                        // 建议根据strConfirmItemRecPath来进行挑选
                        if (String.IsNullOrEmpty(strConfirmItemRecPath) == true)
                        {
                            // 容错!
                            strOutputItemRecPath = aPath[0];

                            strRecoverComment += "册条码号 " + strItemBarcode + " 有 "
                                + aPath.Count.ToString() + " 条重复记录,因受容错要求所迫,权且采用其中第一个记录 "
                                + strOutputItemRecPath + " 来进行借阅操作。";

                            // 是否需要重新装载?
                            bNeedReload = false;    // 所取得的第一个路径,其记录已经装载
                        }
                        else
                        {

                            ///// 
                            nRet = aPath.IndexOf(strConfirmItemRecPath);
                            if (nRet != -1)
                            {
                                strOutputItemRecPath = aPath[nRet];
                                strRecoverComment += "册条码号 " + strItemBarcode + " 有 "
                                    + aPath.Count.ToString() + " 条重复记录,经过找到strConfirmItemRecPath=[" + strConfirmItemRecPath + "]"
                                    + "来进行借阅操作。";

                                // 是否需要重新装载?
                                if (nRet != 0)
                                    bNeedReload = true; // 第一个以外的路径才需要装载

                            }
                            else
                            {
                                // 容错
                                strOutputItemRecPath = aPath[0];

                                strRecoverComment += "册条码号 " + strItemBarcode + " 有 "
                                    + aPath.Count.ToString() + " 条重复记录,在其中无法找到strConfirmItemRecPath=[" + strConfirmItemRecPath + "]的记录"
                                    + "因受容错要求所迫,权且采用其中第一个记录 "
                                    + strOutputItemRecPath + " 来进行借阅操作。";

                                // 是否需要重新装载?
                                bNeedReload = false;    // 所取得的第一个路径,其记录已经装载

                                /* 
                                                                    strError = "册条码号 " + strItemBarcode + " 有 "
                                                                        + aPath.Count.ToString() + " 条重复记录,在其中无法找到strConfirmItemRecPath=[" + strConfirmItemRecPath + "]的记录";
                                                                    return -1;
                                 * */

                            }
                        }


                    } // if (aPath.Count > 1)
                    else
                    {

                        Debug.Assert(nRet == 1, "");
                        Debug.Assert(aPath.Count == 1, "");

                        if (nRet == 1)
                        {
                            strOutputItemRecPath = aPath[0];

                            // 是否需要重新装载?
                            bNeedReload = false;    // 所取得的第一个路径,其记录已经装载
                        }
                    }


                    // 重新装载
                    if (bNeedReload == true)
                    {
                        string strMetaData = "";
                        lRet = channel.GetRes(strOutputItemRecPath,
                            out strItemXml,
                            out strMetaData,
                            out item_timestamp,
                            out strOutputItemRecPath,
                            out strError);
                        if (lRet == -1)
                        {
                            strError = "根据strOutputItemRecPath '" + strOutputItemRecPath + "' 重新获得册记录失败: " + strError;
                            return -1;
                        }

                        // 需要检查记录中的<barcode>元素值是否匹配册条码号

                    }
                }

                ////

                XmlDocument itemdom = null;
                nRet = LibraryApplication.LoadToDom(strItemXml,
                    out itemdom,
                    out strError);
                if (nRet == -1)
                {
                    strError = "装载册记录进入XML DOM时发生错误: " + strError;
                    goto ERROR1;
                }

                // 修改读者记录
                // 修改册记录

                nRet = BorrowChangeReaderAndItemRecord(
                    // Channels,
                    channel,
                    strItemBarcode,
                    strReaderBarcode,
                    domLog,
                    strRecoverComment,
                    strLibraryCode,
                    ref readerdom,
                    ref itemdom,
                    out strError);
                if (nRet == -1)
                    goto ERROR1;

                // 写回读者、册记录
                byte[] output_timestamp = null;
                string strOutputPath = "";


                // 写回读者记录
                lRet = channel.DoSaveTextRes(strOutputReaderRecPath,
                    readerdom.OuterXml,
                    false,
                    "content,ignorechecktimestamp",
                    reader_timestamp,
                    out output_timestamp,
                    out strOutputPath,
                    out strError);
                if (lRet == -1)
                    goto ERROR1;

                // 写回册记录
                lRet = channel.DoSaveTextRes(strOutputItemRecPath,
                    itemdom.OuterXml,
                    false,
                    "content,ignorechecktimestamp",
                    item_timestamp,
                    out output_timestamp,
                    out strOutputPath,
                    out strError);
                if (lRet == -1)
                    goto ERROR1;

            }


            return 0;
            ERROR1:
            if (level == RecoverLevel.LogicAndSnapshot)
            {
                level = RecoverLevel.Snapshot;
                goto DO_SNAPSHOT;
            }
            return -1;
        }
예제 #27
0
        // 刷新数据库定义
        // parameters:
        //      strDatabaseInfo 要刷新的下属文件特性。<refreshStyle include="keys,browse" exclude="">(表示只刷新keys和browse两个重要配置文件)或者<refreshStyle include="*" exclude="template">(表示刷新全部文件,但是不要刷新template) 如果参数值为空,表示全部刷新
        //      strOutputInfo   返回keys定义发生改变的数据库名。"<keysChanged dbpaths='http://*****:*****@biblioDbName='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的书目库(biblioDbName属性)相关<database>元素没有找到";
                        goto ERROR1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许刷新书目库的定义";
                        goto ERROR1;
                    }

                    string strSyntax = DomUtil.GetAttr(nodeDatabase, "syntax");
                    if (String.IsNullOrEmpty(strSyntax) == true)
                        strSyntax = "unimarc";

                    string strUsage = "";
                    string strIssueDbName = DomUtil.GetAttr(nodeDatabase, "issueDbName");
                    if (String.IsNullOrEmpty(strIssueDbName) == true)
                        strUsage = "book";
                    else
                        strUsage = "series";

                    // 刷新书目库
                    string strTemplateDir = this.DataDir + "\\templates\\" + "biblio_" + strSyntax + "_" + strUsage;

                    nRet = RefreshDatabase(channel,
                        strTemplateDir,
                        strName,
                        strInclude,
                        strExclude,
                        out strError);
                    if (nRet == -1)
                    {
                        strError = "刷新小书目库 '" + strName + "' 定义时发生错误: " + strError;
                        goto ERROR1;
                    }
                    if (nRet == 1)
                        keyschanged_dbnames.Add(strName);

                    // 刷新实体库
                    string strEntityDbName = DomUtil.GetAttr(nodeDatabase, "name");
                    if (String.IsNullOrEmpty(strEntityDbName) == false)
                    {
                        strTemplateDir = this.DataDir + "\\templates\\" + "item";

                        nRet = RefreshDatabase(channel,
                            strTemplateDir,
                            strEntityDbName,
                            strInclude,
                            strExclude,
                            out strError);
                        if (nRet == -1)
                        {
                            strError = "刷新书目库 '" + strName + "' 所从属的实体库 '" + strEntityDbName + "' 定义时发生错误: " + strError;
                            goto ERROR1;
                        }
                        if (nRet == 1)
                            keyschanged_dbnames.Add(strEntityDbName);
                    }

                    // 刷新订购库
                    string strOrderDbName = DomUtil.GetAttr(nodeDatabase, "orderDbName");
                    if (String.IsNullOrEmpty(strOrderDbName) == false)
                    {
                        strTemplateDir = this.DataDir + "\\templates\\" + "order";

                        nRet = RefreshDatabase(channel,
                            strTemplateDir,
                            strOrderDbName,
                            strInclude,
                            strExclude,
                            out strError);
                        if (nRet == -1)
                        {
                            strError = "刷新书目库 '" + strName + "' 所从属的订购库 '" + strOrderDbName + "' 定义时发生错误: " + strError;
                            goto ERROR1;
                        }
                        if (nRet == 1)
                            keyschanged_dbnames.Add(strOrderDbName);
                    }

                    // 刷新期库
                    if (String.IsNullOrEmpty(strIssueDbName) == false)
                    {
                        strTemplateDir = this.DataDir + "\\templates\\" + "issue";

                        nRet = RefreshDatabase(channel,
                            strTemplateDir,
                            strIssueDbName,
                            strInclude,
                            strExclude,
                            out strError);
                        if (nRet == -1)
                        {
                            strError = "刷新书目库 '" + strName + "' 所从属的期库 '" + strIssueDbName + "' 定义时发生错误: " + strError;
                            goto ERROR1;
                        }
                        if (nRet == 1)
                            keyschanged_dbnames.Add(strIssueDbName);
                    }

                    // 刷新评注库
                    string strCommentDbName = DomUtil.GetAttr(nodeDatabase, "commentDbName");
                    if (String.IsNullOrEmpty(strCommentDbName) == false)
                    {
                        strTemplateDir = this.DataDir + "\\templates\\" + "comment";

                        nRet = RefreshDatabase(channel,
                            strTemplateDir,
                            strCommentDbName,
                            strInclude,
                            strExclude,
                            out strError);
                        if (nRet == -1)
                        {
                            strError = "刷新书目库 '" + strName + "' 所从属的评注库 '" + strCommentDbName + "' 定义时发生错误: " + strError;
                            goto ERROR1;
                        }
                        if (nRet == 1)
                            keyschanged_dbnames.Add(strCommentDbName);
                    }

                    continue;
                }

                // 单独刷新实体库
                if (this.IsItemDbName(strName) == true)
                {
                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@name='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的实体库(name属性)相关<database>元素没有找到";
                        goto ERROR1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许刷新实体库的定义";
                        goto ERROR1;
                    }

                    // 刷新实体库
                    string strTemplateDir = this.DataDir + "\\templates\\" + "item";

                    nRet = RefreshDatabase(channel,
                        strTemplateDir,
                        strName,
                        strInclude,
                        strExclude,
                        out strError);
                    if (nRet == -1)
                    {
                        strError = "刷新实体库 '" + strName + "' 定义时发生错误: " + strError;
                        goto ERROR1;
                    }
                    if (nRet == 1)
                        keyschanged_dbnames.Add(strName);

                    continue;
                }

                // 单独刷新订购库
                if (this.IsOrderDbName(strName) == true)
                {
                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@orderDbName='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的订购库(orderDbName属性)相关<database>元素没有找到";
                        goto ERROR1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许刷新订购库的定义";
                        goto ERROR1;
                    }

                    // 刷新订购库
                    string strTemplateDir = this.DataDir + "\\templates\\" + "order";
                    nRet = RefreshDatabase(channel,
                        strTemplateDir,
                        strName,
                        strInclude,
                        strExclude,
                        out strError);
                    if (nRet == -1)
                    {
                        strError = "刷新订购库 '" + strName + "' 定义时发生错误: " + strError;
                        goto ERROR1;
                    }
                    if (nRet == 1)
                        keyschanged_dbnames.Add(strName);

                    continue;
                }

                // 单独刷新期库
                if (this.IsIssueDbName(strName) == true)
                {
                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@issueDbName='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的期库(issueDbName属性)相关<database>元素没有找到";
                        goto ERROR1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许刷新期库的定义";
                        goto ERROR1;
                    }

                    // 刷新期库
                    string strTemplateDir = this.DataDir + "\\templates\\" + "issue";

                    nRet = RefreshDatabase(channel,
                        strTemplateDir,
                        strName,
                        strInclude,
                        strExclude,
                        out strError);
                    if (nRet == -1)
                    {
                        strError = "刷新期库 '" + strName + "' 定义时发生错误: " + strError;
                        goto ERROR1;
                    }
                    if (nRet == 1)
                        keyschanged_dbnames.Add(strName);

                    continue;
                }

                // 单独刷新评注库
                if (this.IsCommentDbName(strName) == true)
                {
                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@commentDbName='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的评注库(commentDbName属性)相关<database>元素没有找到";
                        goto ERROR1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许刷新评注库的定义";
                        goto ERROR1;
                    }

                    // 刷新评注库
                    string strTemplateDir = this.DataDir + "\\templates\\" + "comment";

                    nRet = RefreshDatabase(channel,
                        strTemplateDir,
                        strName,
                        strInclude,
                        strExclude,
                        out strError);
                    if (nRet == -1)
                    {
                        strError = "刷新评注库 '" + strName + "' 定义时发生错误: " + strError;
                        goto ERROR1;
                    }
                    if (nRet == 1)
                        keyschanged_dbnames.Add(strName);

                    continue;
                }

                // 刷新读者库
                if (this.IsReaderDbName(strName) == true)
                {
                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("readerdbgroup/database[@name='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的读者库(name属性)相关<database>元素没有找到";
                        goto ERROR1;
                    }

                    // 2012/9/9
                    // 分馆用户只允许刷新属于管辖分馆的读者库
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        string strExistLibraryCode = DomUtil.GetAttr(nodeDatabase, "libraryCode");

                        if (string.IsNullOrEmpty(strExistLibraryCode) == true
                            || StringUtil.IsInList(strExistLibraryCode, strLibraryCodeList) == false)
                        {
                            strError = "刷新读者库 '" + strName + "' 定义被拒绝。当前用户只能刷新图书馆代码完全完全属于 '" + strLibraryCodeList + "' 范围的读者库定义";
                            goto ERROR1;
                        }
                    }

                    // 刷新读者库
                    string strTemplateDir = this.DataDir + "\\templates\\" + "reader";

                    nRet = RefreshDatabase(channel,
                        strTemplateDir,
                        strName,
                        strInclude,
                        strExclude,
                        out strError);
                    if (nRet == -1)
                    {
                        strError = "刷新读者库 '" + strName + "' 定义时发生错误: " + strError;
                        goto ERROR1;
                    }
                    if (nRet == 1)
                        keyschanged_dbnames.Add(strName);

                    continue;
                }

                // 刷新预约到书库
                if (this.ArrivedDbName == strName)
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许刷新预约到书库的定义";
                        goto ERROR1;
                    }

                    // 刷新预约到书库
                    string strTemplateDir = this.DataDir + "\\templates\\" + "arrived";
                    nRet = RefreshDatabase(channel,
                        strTemplateDir,
                        strName,
                        strInclude,
                        strExclude,
                        out strError);
                    if (nRet == -1)
                    {
                        strError = "刷新预约到书库 '" + strName + "' 定义时发生错误: " + strError;
                        goto ERROR1;
                    }
                    if (nRet == 1)
                        keyschanged_dbnames.Add(strName);
                    continue;
                }

                // 刷新违约金库
                if (this.AmerceDbName == strName)
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许刷新违约金库的定义";
                        goto ERROR1;
                    }

                    // 刷新违约金库
                    string strTemplateDir = this.DataDir + "\\templates\\" + "amerce";
                    nRet = RefreshDatabase(channel,
                        strTemplateDir,
                        strName,
                        strInclude,
                        strExclude,
                        out strError);
                    if (nRet == -1)
                    {
                        strError = "刷新违约金库 '" + strName + "' 定义时发生错误: " + strError;
                        goto ERROR1;
                    }
                    if (nRet == 1)
                        keyschanged_dbnames.Add(strName);

                    continue;
                }

                // 刷新发票库
                if (this.InvoiceDbName == strName)
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许刷新发票库的定义";
                        goto ERROR1;
                    }

                    // 刷新发票库
                    string strTemplateDir = this.DataDir + "\\templates\\" + "invoice";
                    nRet = RefreshDatabase(channel,
                        strTemplateDir,
                        strName,
                        strInclude,
                        strExclude,
                        out strError);
                    if (nRet == -1)
                    {
                        strError = "刷新发票库 '" + strName + "' 定义时发生错误: " + strError;
                        goto ERROR1;
                    }
                    if (nRet == 1)
                        keyschanged_dbnames.Add(strName);

                    continue;
                }

                // 刷新消息库
                if (this.MessageDbName == strName)
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许刷新消息库的定义";
                        goto ERROR1;
                    }

                    // 刷新消息库
                    string strTemplateDir = this.DataDir + "\\templates\\" + "message";
                    nRet = RefreshDatabase(channel,
                        strTemplateDir,
                        strName,
                        strInclude,
                        strExclude,
                        out strError);
                    if (nRet == -1)
                    {
                        strError = "刷新消息库 '" + strName + "' 定义时发生错误: " + strError;
                        goto ERROR1;
                    }
                    if (nRet == 1)
                        keyschanged_dbnames.Add(strName);

                    continue;
                }

                // 刷新实用库
                if (IsUtilDbName(strName) == true)
                {
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("utilDb/database[@name='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "不存在name属性值为 '" + strName + "' 的<utilDb/database>的元素";
                        goto ERROR1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许刷新实用库的定义";
                        goto ERROR1;
                    }

                    string strType = DomUtil.GetAttr(nodeDatabase, "type").ToLower();

                    // 刷新实用库
                    string strTemplateDir = this.DataDir + "\\templates\\" + strType;
                    nRet = RefreshDatabase(channel,
                        strTemplateDir,
                        strName,
                        strInclude,
                        strExclude,
                        out strError);
                    if (nRet == -1)
                    {
                        strError = "刷新实用库 '" + strName + "' 定义时发生错误: " + strError;
                        goto ERROR1;
                    }
                    if (nRet == 1)
                        keyschanged_dbnames.Add(strName);
                    continue;
                }

                strError = "数据库名 '" + strName + "' 不属于 dp2library 目前管辖的范围...";
                goto ERROR1;
            }

            // 2015/6/13
            if (keyschanged_dbnames.Count > 0)
            {
                nRet = InitialKdbs(
                    Channels,
                    out strError);
                if (nRet == -1)
                    return -1;
                // 重新初始化虚拟库定义
                this.vdbs = null;
                nRet = this.InitialVdbs(Channels,
                    out strError);
                if (nRet == -1)
                    return -1;
            }

            if (bAutoRebuildKeys == true
                && keyschanged_dbnames.Count > 0)
            {
                nRet = StartRebuildKeysTask(StringUtil.MakePathList(keyschanged_dbnames, ","),
            out strError);
                if (nRet == -1)
                    return -1;
            }

            {
                // 增加WebServiceUrl部分
                for (int i = 0; i < keyschanged_dbnames.Count; i++)
                {
                    keyschanged_dbnames[i] = this.WsUrl.ToLower() + "?" + keyschanged_dbnames[i];
                }

                XmlDocument dom = new XmlDocument();
                dom.LoadXml("<keysChanged />");
                DomUtil.SetAttr(dom.DocumentElement, "dbpaths", StringUtil.MakePathList(keyschanged_dbnames, ";"));
                strOutputInfo = dom.OuterXml;
            }

            return 0;
        ERROR1:
            if (keyschanged_dbnames.Count > 0)
            {
                // 增加WebServiceUrl部分
                for (int i = 0; i < keyschanged_dbnames.Count; i++)
                {
                    keyschanged_dbnames[i] = this.WsUrl.ToLower() + "?" + keyschanged_dbnames[i];
                }

                XmlDocument dom = new XmlDocument();
                dom.LoadXml("<keysChanged />");
                DomUtil.SetAttr(dom.DocumentElement, "dbpaths", StringUtil.MakePathList(keyschanged_dbnames, ";"));
                strOutputInfo = dom.OuterXml;
            }
            return -1;
        }
예제 #28
0
        // Amerce() API 恢复动作
        /*
<root>
  <operation>amerce</operation> 操作类型
  <action>amerce</action> 具体动作。有amerce undo modifyprice
  <readerBarcode>...</readerBarcode> 读者证条码号
  <!-- <idList>...<idList> ID列表,逗号间隔 已废止 -->
  <amerceItems>
	<amerceItem id="..." newPrice="..." newComment="..." /> newComment中内容追加或替换原来的注释内容。到底是追加还是覆盖,取决于第一个字符是否为'>'还是'<',前者为追加(这时第一个字符不被当作内容)。如果第一个字符不是这两者之一,则默认为追加
	...
  </amerceItems>
  <amerceRecord recPath='...'><root><itemBarcode>0000001</itemBarcode><readerBarcode>R0000002</readerBarcode><state>amerced</state><id>632958375041543888-1</id><over>31day</over><borrowDate>Sat, 07 Oct 2006 09:04:28 GMT</borrowDate><borrowPeriod>30day</borrowPeriod><returnDate>Thu, 07 Dec 2006 09:04:27 GMT</returnDate><returnOperator>test</returnOperator></root></amerceRecord> 在罚款库中创建的新记录。注意<amerceRecord>元素可以重复。<amerceRecord>元素内容里面的<itemBarcode><readerBarcode><id>等具备了足够的信息。
  <operator>test</operator> 操作者
  <operTime>Fri, 08 Dec 2006 10:09:36 GMT</operTime> 操作时间
  
  <readerRecord recPath='...'>...</readerRecord>	最新读者记录
</root>

<root>
  <operation>amerce</operation> 
  <action>undo</action> 
  <readerBarcode>...</readerBarcode> 读者证条码号
  <!-- <idList>...<idList> ID列表,逗号间隔 已废止 -->
  <amerceItems>
	<amerceItem id="..." newPrice="..."/>
	...
  </amerceItems>
  <amerceRecord recPath='...'><root><itemBarcode>0000001</itemBarcode><readerBarcode>R0000002</readerBarcode><state>amerced</state><id>632958375041543888-1</id><over>31day</over><borrowDate>Sat, 07 Oct 2006 09:04:28 GMT</borrowDate><borrowPeriod>30day</borrowPeriod><returnDate>Thu, 07 Dec 2006 09:04:27 GMT</returnDate><returnOperator>test</returnOperator></root></amerceRecord> Undo所去掉的罚款库记录
  <operator>test</operator> 
  <operTime>Fri, 08 Dec 2006 10:12:20 GMT</operTime> 
  
  <readerRecord recPath='...'>...</readerRecord>	最新读者记录

</root>

<root>
  <operation>amerce</operation> 
  <action>modifyprice</action> 
  <readerBarcode>...</readerBarcode> 读者证条码号
  <amerceItems>
	<amerceItem id="..." newPrice="..." newComment="..."/> newComment中内容追加或替换原来的注释内容。到底是追加还是覆盖,取决于第一个字符是否为'>'还是'<',前者为追加(这时第一个字符不被当作内容)。如果第一个字符不是这两者之一,则默认为追加
	...
  </amerceItems>
  <!-- modifyprice操作时不产生<amerceRecord>元素 -->
  <operator>test</operator> 
  <operTime>Fri, 08 Dec 2006 10:12:20 GMT</operTime> 
  
  <oldReaderRecord recPath='...'>...</oldReaderRecord>	操作前旧的读者记录。<oldReaderRecord>元素是modifyprice操作时特有的元素
  <readerRecord recPath='...'>...</readerRecord>	最新读者记录

</root>

2007/12/18
<root>
  <operation>amerce</operation> 操作类型
  <action>expire</action> 以停代金到期
  <readerBarcode>...</readerBarcode> 读者证条码号
  <expiredOverdues> 已经到期的若干<overdue>元素
	<overdue ... />
	...
  </expiredOverdues>
  <operator>test</operator> 操作者 如果为#readersMonitor,表示为后台线程
  <operTime>Fri, 08 Dec 2006 10:09:36 GMT</operTime> 操作时间
  
  <readerRecord recPath='...'>...</readerRecord>	最新读者记录
</root>
         * 
2008/6/20
<root>
  <operation>amerce</operation> 
  <action>modifycomment</action> 
  <readerBarcode>...</readerBarcode> 读者证条码号
  <amerceItems>
	<amerceItem id="..." newComment="..."/> newComment中内容追加或替换原来的注释内容。到底是追加还是覆盖,取决于第一个字符是否为'>'还是'<',前者为追加(这时第一个字符不被当作内容)。如果第一个字符不是这两者之一,则默认为追加
	...
  </amerceItems>
  <!-- modifycomment操作时不产生<amerceRecord>元素 -->
  <operator>test</operator> 
  <operTime>Fri, 08 Dec 2006 10:12:20 GMT</operTime> 
  
  <oldReaderRecord recPath='...'>...</oldReaderRecord>	操作前旧的读者记录。<oldReaderRecord>元素是modifycomment操作时特有的元素
  <readerRecord recPath='...'>...</readerRecord>	最新读者记录
</root>

         * * 
         * */
        public int RecoverAmerce(
            RmsChannelCollection Channels,
            RecoverLevel level,
            XmlDocument domLog,
            out string strError)
        {
            strError = "";

            // 暂时把Robust当作Logic处理
            if (level == RecoverLevel.Robust)
                level = RecoverLevel.Logic;


            long lRet = 0;
            int nRet = 0;

            RmsChannel channel = Channels.GetChannel(this.WsUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }

            DO_SNAPSHOT:

            string strAction = DomUtil.GetElementText(domLog.DocumentElement,
                "action");

            // 快照恢复
            if (level == RecoverLevel.Snapshot)
            {

                byte[] timestamp = null;
                byte[] output_timestamp = null;
                string strOutputPath = "";

                if (strAction == "amerce")
                {
                    XmlNodeList nodes = domLog.DocumentElement.SelectNodes("amerceRecord");

                    int nErrorCount = 0;
                    for (int i = 0; i < nodes.Count; i++)
                    {
                        XmlNode node = nodes[i];
                        string strRecord = node.InnerText;
                        string strRecPath = DomUtil.GetAttr(node, "recPath");


                        // 写违约金记录
                        string strError0 = "";
                        lRet = channel.DoSaveTextRes(strRecPath,
            strRecord,
            false,
            "content,ignorechecktimestamp",
            timestamp,
            out output_timestamp,
            out strOutputPath,
            out strError0);
                        if (lRet == -1)
                        {
                            // 继续循环
                            if (strError != "")
                                strError += "\r\n";
                            strError += "写入违约金记录 '" + strRecPath + "' 时发生错误: " + strError0;
                            nErrorCount++;
                        }
                    }

                    if (nErrorCount > 0)
                        return -1;
                }
                else if (strAction == "undo")
                {
                    XmlNodeList nodes = domLog.DocumentElement.SelectNodes("amerceRecord");

                    int nErrorCount = 0;
                    for (int i = 0; i < nodes.Count; i++)
                    {
                        XmlNode node = nodes[i];
                        string strRecPath = DomUtil.GetAttr(node, "recPath");

                        int nRedoCount = 0;
                        string strError0 = "";
                    REDO:
                        // 删除违约金记录
                        lRet = channel.DoDeleteRes(strRecPath,
                            timestamp,
                            out output_timestamp,
                            out strError0);
                        if (lRet == -1)
                        {
                            if (channel.ErrorCode == ChannelErrorCode.NotFound)
                                continue;   // 记录本来就不存在
                            if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch)
                            {
                                if (nRedoCount < 10)
                                {
                                    timestamp = output_timestamp;
                                    nRedoCount++;
                                    goto REDO;
                                }
                            }

                            // 继续循环
                            if (strError != "")
                                strError += "\r\n";
                            strError += "删除违约金记录 '" + strRecPath + "' 时发生错误: " + strError0;
                            nErrorCount++;
                        }
                    } // end of for

                    if (nErrorCount > 0)
                        return -1;
                }
                else if (strAction == "modifyprice")
                {
                    // 这里什么都不作,只等后面用快照的读者记录来恢复
                }
                else if (strAction == "expire")
                {
                    // 这里什么都不作,只等后面用快照的读者记录来恢复

                }
                else if (strAction == "modifycomment")
                {
                    // 这里什么都不作,只等后面用快照的读者记录来恢复
                }
                else if (strAction == "appendcomment")
                {
                    // 这里什么都不作,只等后面用快照的读者记录来恢复
                }
                else
                {
                    strError = "未知的<action>类型: " + strAction;
                    return -1;
                }

                {
                    XmlNode node = null;
                    // 写入读者记录
                    string strReaderRecord = DomUtil.GetElementText(domLog.DocumentElement,
                        "readerRecord",
                        out node);
                    string strReaderRecPath = DomUtil.GetAttr(node, "recPath");

                    // 写读者记录
                    lRet = channel.DoSaveTextRes(strReaderRecPath,
        strReaderRecord,
        false,
        "content,ignorechecktimestamp",
        timestamp,
        out output_timestamp,
        out strOutputPath,
        out strError);
                    if (lRet == -1)
                    {
                        strError = "写入读者记录 '" + strReaderRecPath + "' 时发生错误: " + strError;
                        return -1;
                    }
                }

                return 0;
            }

            // 逻辑恢复或者混合恢复
            if (level == RecoverLevel.Logic
                || level == RecoverLevel.LogicAndSnapshot)
            {
                string strReaderBarcode = DomUtil.GetElementText(domLog.DocumentElement,
                    "readerBarcode");
                if (String.IsNullOrEmpty(strReaderBarcode) == true)
                {
                    strError = "日志记录中缺乏<readerBarcode>元素";
                    return -1;
                }
                string strLibraryCode = DomUtil.GetElementText(domLog.DocumentElement,
                    "libraryCode");

                string strOperator = DomUtil.GetElementText(domLog.DocumentElement,
                    "operator");
                string strOperTime = DomUtil.GetElementText(domLog.DocumentElement,
                    "operTime");

                /*
                string strAmerceItemIdList = DomUtil.GetElementText(domLog.DocumentElement,
                    "idList");
                if (String.IsNullOrEmpty(strAmerceItemIdList) == true)
                {
                    strError = "日志记录中缺乏<idList>元素";
                    return -1;
                }
                 * */

                AmerceItem[] amerce_items = ReadAmerceItemList(domLog);


                // 读入读者记录
                string strReaderXml = "";
                string strOutputReaderRecPath = "";
                byte[] reader_timestamp = null;
                nRet = this.GetReaderRecXml(
                    // Channels,
                    channel,
                    strReaderBarcode,
                    out strReaderXml,
                    out strOutputReaderRecPath,
                    out reader_timestamp,
                    out strError);
                if (nRet == 0)
                {
                    strError = "读者证条码号 '" + strReaderBarcode + "' 不存在";
                    goto ERROR1;
                }
                if (nRet == -1)
                {
                    strError = "读入读者记录时发生错误: " + strError;
                    goto ERROR1;
                }

                XmlDocument readerdom = null;
                nRet = LibraryApplication.LoadToDom(strReaderXml,
                    out readerdom,
                    out strError);
                if (nRet == -1)
                {
                    strError = "装载读者记录进入XML DOM时发生错误: " + strError;
                    goto ERROR1;
                }

                byte[] output_timestamp = null;
                string strOutputPath = "";

                if (strAction == "amerce")
                {
                    List<string> NotFoundIds = null;
                    List<string> Ids = null;
                    List<string> AmerceRecordXmls = null;
                    // 交违约金:在读者记录中去除所选的<overdue>元素,并且构造一批新记录准备加入违约金库
                    // return:
                    //      -1  error
                    //      0   读者dom没有变化
                    //      1   读者dom发生了变化
                    nRet = DoAmerceReaderXml(
                        strLibraryCode,
                        ref readerdom,
                        amerce_items,
                        strOperator,
                        strOperTime,
                        out AmerceRecordXmls,
                        out NotFoundIds,
                        out Ids,
                        out strError);
                    if (nRet == -1)
                    {
                        // 在错误信息后面增补每个id对应的amerce record
                        if (NotFoundIds != null && NotFoundIds.Count > 0)
                        {
                            strError += "。读者证条码号为 " + strReaderBarcode + ",日志记录中相关的AmerceRecord如下:\r\n" + GetAmerceRecordStringByID(domLog, NotFoundIds);
                        }

                        goto ERROR1;
                    }

                    // 如果有精力,可以把AmerceRecordXmls和日志记录中的<amerceRecord>逐个进行核对


                    // 写入违约金记录
                    XmlNodeList nodes = domLog.DocumentElement.SelectNodes("amerceRecord");

                    for (int i = 0; i < nodes.Count; i++)
                    {
                        XmlNode node = nodes[i];
                        string strRecord = node.InnerText;
                        string strRecPath = DomUtil.GetAttr(node, "recPath");


                        // 写违约金记录
                        lRet = channel.DoSaveTextRes(strRecPath,
                            strRecord,
                            false,
                            "content,ignorechecktimestamp",
                            null,
                            out output_timestamp,
                            out strOutputPath,
                            out strError);
                        if (lRet == -1)
                        {
                            strError = "写入违约金记录 '" + strRecPath + "' 时发生错误: " + strError;
                            goto ERROR1;
                        }
                    }
                }

                if (strAction == "undo")
                {
                    XmlNodeList nodes = domLog.DocumentElement.SelectNodes("amerceRecord");

                    // 看看根下面是否有overdues元素
                    XmlNode root = readerdom.DocumentElement.SelectSingleNode("overdues");
                    if (root == null)
                    {
                        root = readerdom.CreateElement("overdues");
                        readerdom.DocumentElement.AppendChild(root);
                    }

                    for (int i = 0; i < nodes.Count; i++)
                    {
                        XmlNode node = nodes[i];
                        string strRecord = node.InnerText;
                        string strRecPath = DomUtil.GetAttr(node, "recPath");


                        // 如果有精力,可以把违约金记录中的id和日志记录<amerceItems>中的id对比检查

                        // 违约金信息加回读者记录
                        string strTempReaderBarcode = "";
                        string strOverdueString = "";

                        // 将违约金记录格式转换为读者记录中的<overdue>元素格式
                        nRet = ConvertAmerceRecordToOverdueString(strRecord,
                            out strTempReaderBarcode,
                            out strOverdueString,
                            out strError);
                        if (nRet == -1)
                            goto ERROR1;

                        if (strTempReaderBarcode != strReaderBarcode)
                        {
                            strError = "<amerceRecord>中的读者证条码号和日志记录中的<readerBarcode>读者证条码号不一致";
                            goto ERROR1;
                        }

                        XmlDocumentFragment fragment = readerdom.CreateDocumentFragment();
                        fragment.InnerXml = strOverdueString;

                        // 2008/11/13 changed
                        XmlNode node_added = root.AppendChild(fragment);
                        Debug.Assert(node_added != null, "");
                        string strReason = DomUtil.GetAttr(node_added, "reason");
                        if (strReason == "押金。")
                        {
                            string strPrice = DomUtil.GetAttr(node_added, "price");

                            if (String.IsNullOrEmpty(strPrice) == false)
                            {
                                // 需要从<foregift>元素中减去这个价格
                                string strContent = DomUtil.GetElementText(readerdom.DocumentElement,
                                    "foregift");


                                string strNegativePrice = "";
                                // 将形如"-123.4+10.55-20.3"的价格字符串反转正负号
                                // parameters:
                                //      bSum    是否要顺便汇总? true表示要汇总
                                nRet = PriceUtil.NegativePrices(strPrice,
                                    false,
                                    out strNegativePrice,
                                    out strError);
                                if (nRet == -1)
                                {
                                    strError = "反转价格字符串 '" + strPrice + "时发生错误: " + strError;
                                    goto ERROR1;
                                }

                                strContent = PriceUtil.JoinPriceString(strContent, strNegativePrice);

                                DomUtil.SetElementText(readerdom.DocumentElement,
                                    "foregift",
                                    strContent);
                                // bReaderDomChanged = true;
                            }
                        }


                        // 删除违约金记录
                        int nRedoCount = 0;
                        byte[] timestamp = null;
                    REDO:
                        // 删除违约金记录
                        lRet = channel.DoDeleteRes(strRecPath,
                            timestamp,
                            out output_timestamp,
                            out strError);
                        if (lRet == -1)
                        {
                            if (channel.ErrorCode == ChannelErrorCode.NotFound)
                                continue;   // 记录本来就不存在
                            if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch)
                            {
                                if (nRedoCount < 10)
                                {
                                    timestamp = output_timestamp;
                                    nRedoCount++;
                                    goto REDO;
                                }
                            }

                            // 是否需要继续循环?
                            strError = "删除违约金记录 '" + strRecPath + "' 时发生错误: " + strError;
                            goto ERROR1;
                        }
                    }

                }

                if (strAction == "modifyprice")
                {
                    nRet = ModifyPrice(ref readerdom,
                        amerce_items,
                        out strError);
                    if (nRet == -1)
                    {
                        strError = "ModifyPrice()时发生错误: " + strError;
                        goto ERROR1;
                    }
                }

                // 2008/6/20
                if (strAction == "modifycomment")
                {
                    nRet = ModifyComment(
                        ref readerdom,
                        amerce_items,
                        out strError);
                    if (nRet == -1)
                    {
                        strError = "ModifyComment()时发生错误: " + strError;
                        goto ERROR1;
                    }
                }

                if (strAction == "expire")
                {
                    // 寻找<expiredOverdues/overdue>元素
                    XmlNodeList nodes = domLog.DocumentElement.SelectNodes("//expiredOverdues/overdue");
                    for (int i = 0; i < nodes.Count; i++)
                    {
                        XmlNode node = nodes[i];
                        string strID = DomUtil.GetAttr(node, "id");

                        if (String.IsNullOrEmpty(strID) == true)
                            continue;

                        // 从读者记录中去掉这个id的<overdue>元素
                        XmlNode nodeOverdue = readerdom.DocumentElement.SelectSingleNode("overdues/overdue[@id='"+strID+"']");
                        if (nodeOverdue != null)
                        {
                            if (nodeOverdue.ParentNode != null)
                                nodeOverdue.ParentNode.RemoveChild(nodeOverdue);
                        }
                    }
                }

                // 写回读者记录
                strReaderXml = readerdom.OuterXml;

                lRet = channel.DoSaveTextRes(strOutputReaderRecPath,
                    strReaderXml,
                    false,
                    "content,ignorechecktimestamp",
                    reader_timestamp,
                    out output_timestamp,
                    out strOutputPath,
                    out strError);
                if (lRet == -1)
                    goto ERROR1;
 
            }

            return 0;

        ERROR1:
            if (level == RecoverLevel.LogicAndSnapshot)
            {
                level = RecoverLevel.Snapshot;
                goto DO_SNAPSHOT;
            }
            return -1;
        }
예제 #29
0
        // 初始化数据库
        int InitializeDatabase(
            RmsChannelCollection Channels,
            string strLibraryCodeList,
            string strDatabaseNames,
            out string strOutputInfo,
            out string strError)
        {
            strOutputInfo = "";
            strError = "";

            int nRet = 0;
            long lRet = 0;

            bool bDbNameChanged = false;    // 初始化后,检索途径名等都可能被改变

            RmsChannel channel = Channels.GetChannel(this.WsUrl);

            string[] names = strDatabaseNames.Split(new char[] { ',' });
            for (int i = 0; i < names.Length; i++)
            {
                string strName = names[i].Trim();
                if (String.IsNullOrEmpty(strName) == true)
                    continue;

                // 书目库整体初始化,也是可以的
                // TODO: 将来可以考虑单独初始化书目库而不删除组内相关库
                if (this.IsBiblioDbName(strName) == true)
                {
                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@biblioDbName='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的书目库(biblioDbName属性)相关<database>元素没有找到";
                        return -1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许初始化书目库";
                        return -1;
                    }

                    // 初始化书目库
                    lRet = channel.DoInitialDB(strName, out strError);
                    if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                    {
                        strError = "初始化小书目库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }

                    bDbNameChanged = true;

                    // 初始化实体库
                    string strEntityDbName = DomUtil.GetAttr(nodeDatabase, "name");
                    if (String.IsNullOrEmpty(strEntityDbName) == false)
                    {
                        lRet = channel.DoInitialDB(strEntityDbName, out strError);
                        if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                        {
                            strError = "初始化书目库 '" + strName + "' 所从属的实体库 '" + strEntityDbName + "' 时发生错误: " + strError;
                            return -1;
                        }
                    }

                    // 初始化订购库
                    string strOrderDbName = DomUtil.GetAttr(nodeDatabase, "orderDbName");
                    if (String.IsNullOrEmpty(strOrderDbName) == false)
                    {
                        lRet = channel.DoInitialDB(strOrderDbName, out strError);
                        if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                        {
                            strError = "初始化书目库 '" + strName + "' 所从属的订购库 '" + strOrderDbName + "' 时发生错误: " + strError;
                            return -1;
                        }
                    }

                    // 初始化期库
                    string strIssueDbName = DomUtil.GetAttr(nodeDatabase, "issueDbName");
                    if (String.IsNullOrEmpty(strIssueDbName) == false)
                    {
                        lRet = channel.DoInitialDB(strIssueDbName, out strError);
                        if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                        {
                            strError = "初始化书目库 '" + strName + "' 所从属的期库 '" + strIssueDbName + "' 时发生错误: " + strError;
                            return -1;
                        }
                    }

                    // 初始化评注库
                    string strCommentDbName = DomUtil.GetAttr(nodeDatabase, "commentDbName");
                    if (String.IsNullOrEmpty(strCommentDbName) == false)
                    {
                        lRet = channel.DoInitialDB(strCommentDbName, out strError);
                        if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                        {
                            strError = "初始化书目库 '" + strName + "' 所从属的评注库 '" + strCommentDbName + "' 时发生错误: " + strError;
                            return -1;
                        }
                    }

                    continue;
                }

                // 单独初始化实体库
                if (this.IsItemDbName(strName) == true)
                {
                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@name='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的实体库(name属性)相关<database>元素没有找到";
                        return -1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许初始化实体库";
                        return -1;
                    }

                    // 初始化实体库
                    lRet = channel.DoInitialDB(strName, out strError);
                    if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                    {
                        strError = "初始化实体库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }

                    bDbNameChanged = true;

                    continue;
                }

                // 单独初始化订购库
                if (this.IsOrderDbName(strName) == true)
                {
                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@orderDbName='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的订购库(orderDbName属性)相关<database>元素没有找到";
                        return -1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许初始化订购库";
                        return -1;
                    }

                    // 初始化订购库
                    lRet = channel.DoInitialDB(strName, out strError);
                    if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                    {
                        strError = "初始化订购库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }

                    bDbNameChanged = true;

                    continue;
                }

                // 单独初始化期库
                if (this.IsIssueDbName(strName) == true)
                {
                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@issueDbName='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的期库(issueDbName属性)相关<database>元素没有找到";
                        return -1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许初始化期库";
                        return -1;
                    }

                    // 初始化期库
                    lRet = channel.DoInitialDB(strName, out strError);
                    if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                    {
                        strError = "初始化期库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }

                    bDbNameChanged = true;

                    continue;
                }

                // 单独初始化评注库
                if (this.IsCommentDbName(strName) == true)
                {
                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("itemdbgroup/database[@commentDbName='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的评注库(commentDbName属性)相关<database>元素没有找到";
                        return -1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许初始化评注库";
                        return -1;
                    }

                    // 初始化评注库
                    lRet = channel.DoInitialDB(strName, out strError);
                    if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                    {
                        strError = "初始化评注库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }

                    bDbNameChanged = true;
                    continue;
                }

                // 初始化读者库
                if (this.IsReaderDbName(strName) == true)
                {
                    // 获得相关配置小节
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("readerdbgroup/database[@name='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "配置DOM中名字为 '" + strName + "' 的读者库(name属性)相关<database>元素没有找到";
                        return -1;
                    }

                    // 2012/9/9
                    // 分馆用户只允许初始化属于管辖分馆的读者库
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        string strExistLibraryCode = DomUtil.GetAttr(nodeDatabase, "libraryCode");

                        if (string.IsNullOrEmpty(strExistLibraryCode) == true
                            || StringUtil.IsInList(strExistLibraryCode, strLibraryCodeList) == false)
                        {
                            strError = "初始化读者库 '" + strName + "' 被拒绝。当前用户只能初始化图书馆代码完全完全属于 '" + strLibraryCodeList + "' 范围的读者库";
                            return -1;
                        }
                    }

                    // 初始化读者库
                    lRet = channel.DoInitialDB(strName, out strError);
                    if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                    {
                        strError = "初始化读者库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }

                    bDbNameChanged = true;

                    continue;
                }

                // 初始化预约到书库
                if (this.ArrivedDbName == strName)
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许初始化预约到书库";
                        return -1;
                    }

                    // 初始化预约到书库
                    lRet = channel.DoInitialDB(strName, out strError);
                    if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                    {
                        strError = "初始化预约到书库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }
                    continue;
                }

                // 初始化违约金库
                if (this.AmerceDbName == strName)
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许初始化违约金库";
                        return -1;
                    }

                    // 初始化违约金库
                    lRet = channel.DoInitialDB(strName, out strError);
                    if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                    {
                        strError = "初始化违约金库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }

                    continue;
                }

                // 初始化发票库
                if (this.InvoiceDbName == strName)
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许初始化发票库";
                        return -1;
                    }

                    // 初始化发票库
                    lRet = channel.DoInitialDB(strName, out strError);
                    if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                    {
                        strError = "初始化发票库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }

                    continue;
                }

                // 初始化消息库
                if (this.MessageDbName == strName)
                {
                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许初始化消息库";
                        return -1;
                    }

                    // 初始化消息库
                    lRet = channel.DoInitialDB(strName, out strError);
                    if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                    {
                        strError = "初始化消息库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }

                    continue;
                }

                // 初始化实用库
                if (IsUtilDbName(strName) == true)
                {
                    XmlNode nodeDatabase = this.LibraryCfgDom.DocumentElement.SelectSingleNode("utilDb/database[@name='" + strName + "']");
                    if (nodeDatabase == null)
                    {
                        strError = "不存在name属性值为 '" + strName + "' 的<utilDb/database>的元素";
                        return -1;
                    }

                    if (SessionInfo.IsGlobalUser(strLibraryCodeList) == false)
                    {
                        strError = "当前用户不是全局用户,不允许初始化实用库";
                        return -1;
                    }

                    // 初始化实用库
                    lRet = channel.DoInitialDB(strName, out strError);
                    if (lRet == -1 && channel.ErrorCode != ChannelErrorCode.NotFound)
                    {
                        strError = "初始化实用库 '" + strName + "' 时发生错误: " + strError;
                        return -1;
                    }
                    continue;
                }

                strError = "数据库名 '" + strName + "' 不属于 dp2library 目前管辖的范围...";
                return -1;
            }

            if (bDbNameChanged == true)
            {
                nRet = InitialKdbs(
                    Channels,
                    out strError);
                if (nRet == -1)
                    return -1;
                /*
                // 重新初始化虚拟库定义
                this.vdbs = null;
                nRet = this.InitialVdbs(Channels,
                    out strError);
                if (nRet == -1)
                    return -1;
                 * */
            }

            return 0;
        }
예제 #30
0
        /*
<root>
  <operation>devolveReaderInfo</operation> 
  <sourceReaderBarcode>...</sourceReaderBarcode> 源读者证条码号
  <targetReaderBarcode>...</targetReaderBarcode> 目标读者证条码号
  <borrows>...</borrows> 移动过去的<borrows>内容,下级为<borrow>元素
  <overdues>...</overdues> 移动过去的<overdue>内容,下级为<overdue>元素
  <sourceReaderRecord recPath='...'>...</sourceReaderRecord>	最新源读者记录
  <targetReaderRecord recPath='...'>...</targetReaderRecord>	最新目标读者记录
  <changedEntityRecord recPath='...' attahchmentIndex='.'>...</changedEntityRecord> 所牵连到的发生了修改的实体记录。此元素的文本即是记录体,但注意为不透明的字符串(HtmlEncoding后的记录字符串)。如果存在attachmentIndex属性,则表明实体记录不在此元素文本中,而在日志记录的附件中
  <operator>test</operator> 
  <operTime>Fri, 08 Dec 2006 10:12:20 GMT</operTime> 
</root>
         * * */
        public int RecoverDevolveReaderInfo(
            RmsChannelCollection Channels,
            RecoverLevel level,
            XmlDocument domLog,
            Stream attachmentLog,
            out string strError)
        {
            strError = "";

            // 暂时把Robust当作Logic处理
            if (level == RecoverLevel.Robust)
                level = RecoverLevel.Logic;

            long lRet = 0;
            int nRet = 0;

            RmsChannel channel = Channels.GetChannel(this.WsUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }

        DO_SNAPSHOT:

            // 快照恢复
            if (level == RecoverLevel.Snapshot)
            {
                /*
                // 观察是否有<warning>元素
                XmlNode nodeWarning = domLog.SelectSingleNode("warning");
                if (nodeWarning != null)
                {
                    // 如果<warning元素存在,表明只能采用逻辑恢复>
                    strError = nodeWarning.InnerText;
                    return -1;
                }
                */

                // 获源读者记录
                XmlNode node = null;
                string strSourceReaderXml = DomUtil.GetElementText(
                    domLog.DocumentElement,
                    "sourceReaderRecord",
                    out node);
                if (node == null)
                {
                    strError = "日志记录中缺<sourceReaderRecord>元素";
                    return -1;
                }
                string strSourceReaderRecPath = DomUtil.GetAttr(node, "recPath");

                byte[] timestamp = null;
                string strOutputPath = "";
                byte[] output_timestamp = null;

                // 写源读者记录
                lRet = channel.DoSaveTextRes(strSourceReaderRecPath,
    strSourceReaderXml,
    false,
    "content,ignorechecktimestamp",
    timestamp,
    out output_timestamp,
    out strOutputPath,
    out strError);
                if (lRet == -1)
                {
                    strError = "写入源读者记录 '" + strSourceReaderRecPath + "' 时发生错误: " + strError;
                    return -1;
                }

                // 获目标读者记录
                node = null;
                string strTargetReaderXml = DomUtil.GetElementText(
                    domLog.DocumentElement,
                    "targetReaderRecord",
                    out node);
                if (node == null)
                {
                    strError = "日志记录中缺<targetReaderRecord>元素";
                    return -1;
                }
                string strTargetReaderRecPath = DomUtil.GetAttr(node, "recPath");

                // 写目标读者记录
                lRet = channel.DoSaveTextRes(strTargetReaderRecPath,
                    strTargetReaderXml,
                    false,
                    "content,ignorechecktimestamp",
                    timestamp,
                    out output_timestamp,
                    out strOutputPath,
                    out strError);
                if (lRet == -1)
                {
                    strError = "写入目标读者记录 '" + strSourceReaderRecPath + "' 时发生错误: " + strError;
                    return -1;
                }

                // 循环,写入相关的若干实体记录
                XmlNodeList nodeEntities = domLog.DocumentElement.SelectNodes("changedEntityRecord");
                for (int i = 0; i < nodeEntities.Count; i++)
                {
                    XmlNode nodeEntity = nodeEntities[i];

                    string strItemRecPath = DomUtil.GetAttr(nodeEntity,
                        "recPath");
                    string strAttachmentIndex = DomUtil.GetAttr(nodeEntity,
                        "attachmentIndex");

                    string strItemXml = "";

                    if (String.IsNullOrEmpty(strAttachmentIndex) == true)
                    {
                        strItemXml = nodeEntity.InnerText;
                        if (String.IsNullOrEmpty(strItemXml) == true)
                        {
                            strError = "<changedEntityRecord>元素缺乏文本内容。";
                            return -1;
                        }
                    }
                    else
                    {
                        // 实体记录在附件中
                        int nAttachmentIndex = 0;
                        try
                        {
                            nAttachmentIndex = Convert.ToInt32(strAttachmentIndex);
                        }
                        catch
                        {
                            strError = "<changedEntityRecord>元素的attachmentIndex属性值'"+strAttachmentIndex+"'格式不正确,应当为>=0的纯数字";
                            return -1;
                        }

                        byte[] baItem = null;
                        nRet = GetAttachmentRecord(
                            attachmentLog,
                            nAttachmentIndex,
                            out baItem,
                            out strError);
                        if (nRet == -1)
                        {
                            strError = "获得 index 为 "+nAttachmentIndex.ToString()+" 的日志附件记录时出错:" + strError;
                            return -1;
                        }
                        strItemXml = Encoding.UTF8.GetString(baItem);
                    }

                    // 写册记录
                    lRet = channel.DoSaveTextRes(strItemRecPath,
                        strItemXml,
                        false,
                        "content,ignorechecktimestamp",
                        timestamp,
                        out output_timestamp,
                        out strOutputPath,
                        out strError);
                    if (lRet == -1)
                    {
                        strError = "写入册记录 '" + strItemRecPath + "' 时发生错误: " + strError;
                        return -1;
                    }
                }

                return 0;
            }

            // 逻辑恢复或者混合恢复
            if (level == RecoverLevel.Logic
                || level == RecoverLevel.LogicAndSnapshot)
            {
                string strOperTimeString = DomUtil.GetElementText(domLog.DocumentElement,
                    "operTime");

                string strSourceReaderBarcode = DomUtil.GetElementText(domLog.DocumentElement,
                    "sourceReaderBarcode");
                if (String.IsNullOrEmpty(strSourceReaderBarcode) == true)
                {
                    strError = "<sourceReaderBarcode>元素值为空";
                    goto ERROR1;
                }

                string strTargetReaderBarcode = DomUtil.GetElementText(domLog.DocumentElement,
                    "targetReaderBarcode");
                if (String.IsNullOrEmpty(strTargetReaderBarcode) == true)
                {
                    strError = "<targetReaderBarcode>元素值为空";
                    goto ERROR1;
                }

                // 读入源读者记录
                string strSourceReaderXml = "";
                string strSourceOutputReaderRecPath = "";
                byte[] source_reader_timestamp = null;

                nRet = this.GetReaderRecXml(
                    // Channels,
                    channel,
                    strSourceReaderBarcode,
                    out strSourceReaderXml,
                    out strSourceOutputReaderRecPath,
                    out source_reader_timestamp,
                    out strError);
                if (nRet == 0)
                {
                    strError = "源读者证条码号 '" + strSourceReaderBarcode + "' 不存在";
                    goto ERROR1;
                }
                if (nRet == -1)
                {
                    strError = "读入证条码号为 '" + strSourceReaderBarcode + "' 的源读者记录时发生错误: " + strError;
                    goto ERROR1;
                }

                XmlDocument source_readerdom = null;
                nRet = LibraryApplication.LoadToDom(strSourceReaderXml,
                    out source_readerdom,
                    out strError);
                if (nRet == -1)
                {
                    strError = "装载源读者记录进入XML DOM时发生错误: " + strError;
                    goto ERROR1;
                }

                //
                // 读入目标读者记录
                string strTargetReaderXml = "";
                string strTargetOutputReaderRecPath = "";
                byte[] target_reader_timestamp = null;

                nRet = this.GetReaderRecXml(
                    // Channels,
                    channel,
                    strTargetReaderBarcode,
                    out strTargetReaderXml,
                    out strTargetOutputReaderRecPath,
                    out target_reader_timestamp,
                    out strError);
                if (nRet == 0)
                {
                    strError = "目标读者证条码号 '" + strTargetReaderBarcode + "' 不存在";
                    goto ERROR1;
                }
                if (nRet == -1)
                {
                    strError = "读入证条码号为 '" + strTargetReaderBarcode + "' 的目标读者记录时发生错误: " + strError;
                    goto ERROR1;
                }

                XmlDocument target_readerdom = null;
                nRet = LibraryApplication.LoadToDom(strTargetReaderXml,
                    out target_readerdom,
                    out strError);
                if (nRet == -1)
                {
                    strError = "装载目标读者记录进入XML DOM时发生错误: " + strError;
                    goto ERROR1;
                }

                Stream tempstream = null;

                // 移动信息
                XmlDocument domTemp = null;
                // 移动借阅信息 -- <borrows>元素内容
                // return:
                //      -1  error
                //      0   not found brrowinfo
                //      1   found and moved
                nRet = DevolveBorrowInfo(
                    // Channels,
                    channel,
                    strSourceReaderBarcode,
                    strTargetReaderBarcode,
                    strOperTimeString,
                    ref source_readerdom,
                    ref target_readerdom,
                    ref domTemp,
                    "",
                    out tempstream,
                    out strError);
                if (nRet == -1)
                    goto ERROR1;

                // 移动超期违约金信息 -- <overdues>元素内容
                // return:
                //      -1  error
                //      0   not found overdueinfo
                //      1   found and moved
                nRet = DevolveOverdueInfo(
                    strSourceReaderBarcode,
                    strTargetReaderBarcode,
                    strOperTimeString,
                    ref source_readerdom,
                    ref target_readerdom,
                    ref domTemp,
                    out strError);
                if (nRet == -1)
                    goto ERROR1;

                // 写回读者记录
                byte[] output_timestamp = null;
                string strOutputPath = "";

                // 写回源读者记录
                lRet = channel.DoSaveTextRes(strSourceOutputReaderRecPath,
                    source_readerdom.OuterXml,
                    false,
                    "content,ignorechecktimestamp",
                    source_reader_timestamp,
                    out output_timestamp,
                    out strOutputPath,
                    out strError);
                if (lRet == -1)
                    goto ERROR1;

                // 写回目标读者记录
                lRet = channel.DoSaveTextRes(strTargetOutputReaderRecPath,
                    target_readerdom.OuterXml,
                    false,
                    "content,ignorechecktimestamp",
                    source_reader_timestamp,
                    out output_timestamp,
                    out strOutputPath,
                    out strError);
                if (lRet == -1)
                    goto ERROR1;
            }

            return 0;
        ERROR1:
            if (level == RecoverLevel.LogicAndSnapshot)
            {
                level = RecoverLevel.Snapshot;
                goto DO_SNAPSHOT;
            }
            return -1;
        }
예제 #31
0
        // 初始化所有数据库
        public int ClearAllDbs(
            RmsChannelCollection Channels,
            out string strError)
        {
            strError = "";

            string strTempError = "";

            RmsChannel channel = Channels.GetChannel(this.WsUrl);
            if (channel == null)
            {
                strError = "GetChannel error";
                return -1;
            }

            long lRet = 0;

            // 大书目库
            for (int i = 0; i < this.ItemDbs.Count; i++)
            {
                ItemDbCfg cfg = this.ItemDbs[i];
                // 实体库
                string strEntityDbName = cfg.DbName;

                if (String.IsNullOrEmpty(strEntityDbName) == false)
                {
                    lRet = channel.DoInitialDB(strEntityDbName,
                        out strTempError);
                    if (lRet == -1)
                    {
                        strError += "清除实体库 '" + strEntityDbName + "' 内数据时候发生错误:" + strTempError + "; ";
                    }
                }

                // 订购库
                string strOrderDbName = cfg.OrderDbName;

                if (String.IsNullOrEmpty(strOrderDbName) == false)
                {
                    lRet = channel.DoInitialDB(strOrderDbName,
                        out strTempError);
                    if (lRet == -1)
                    {
                        strError += "清除订购库 '" + strOrderDbName + "' 内数据时候发生错误:" + strTempError + "; ";
                    }
                }

                // 期库
                string strIssueDbName = cfg.IssueDbName;

                if (String.IsNullOrEmpty(strIssueDbName) == false)
                {
                    lRet = channel.DoInitialDB(strIssueDbName,
                        out strTempError);
                    if (lRet == -1)
                    {
                        strError += "清除期库 '" + strIssueDbName + "' 内数据时候发生错误:" + strTempError + "; ";
                    }
                }

                // 小书目库
                string strBiblioDbName = cfg.BiblioDbName;

                if (String.IsNullOrEmpty(strBiblioDbName) == false)
                {
                    lRet = channel.DoInitialDB(strBiblioDbName,
                        out strTempError);
                    if (lRet == -1)
                    {
                        strError += "清除小书目库 '" + strBiblioDbName + "' 内数据时候发生错误:" + strTempError + "; ";
                    }
                }
            }

            // 读者库
            for (int i = 0; i < this.ReaderDbs.Count; i++)
            {
                string strDbName = this.ReaderDbs[i].DbName;

                if (String.IsNullOrEmpty(strDbName) == false)
                {
                    lRet = channel.DoInitialDB(strDbName,
                        out strTempError);
                    if (lRet == -1)
                    {
                        strError += "清除读者库 '" + strDbName + "' 内数据时候发生错误:" + strTempError + "; ";
                    }
                }
            }

            // 预约到书队列库
            if (String.IsNullOrEmpty(this.ArrivedDbName) == false)
            {
                string strDbName = this.ArrivedDbName;
                lRet = channel.DoInitialDB(strDbName,
                    out strTempError);
                if (lRet == -1)
                {
                    strError += "清除预约到书库 '" + strDbName + "' 内数据时候发生错误:" + strTempError + "; ";
                }

            }

            // 违约金库
            if (String.IsNullOrEmpty(this.AmerceDbName) == false)
            {
                string strDbName = this.AmerceDbName;
                lRet = channel.DoInitialDB(strDbName,
                    out strTempError);
                if (lRet == -1)
                {
                    strError += "清除违约金库 '" + strDbName + "' 内数据时候发生错误:" + strTempError + "; ";
                }
            }

            // 发票库
            if (String.IsNullOrEmpty(this.InvoiceDbName) == false)
            {
                string strDbName = this.InvoiceDbName;
                lRet = channel.DoInitialDB(strDbName,
                    out strTempError);
                if (lRet == -1)
                {
                    strError += "清除发票库 '" + strDbName + "' 内数据时候发生错误:" + strTempError + "; ";
                }
            }

            // 消息库
            if (String.IsNullOrEmpty(this.MessageDbName) == false)
            {
                string strDbName = this.MessageDbName;
                lRet = channel.DoInitialDB(strDbName,
                    out strTempError);
                if (lRet == -1)
                {
                    strError += "清除消息库 '" + strDbName + "' 内数据时候发生错误:" + strTempError + "; ";
                }
            }

            // 实用库
            XmlNodeList nodes = this.LibraryCfgDom.DocumentElement.SelectNodes("utilDb/database");
            for (int i = 0; i < nodes.Count; i++)
            {
                XmlNode node = nodes[i];
                string strDbName = DomUtil.GetAttr(node, "name");
                string strType = DomUtil.GetAttr(node, "type");
                if (String.IsNullOrEmpty(strDbName) == false)
                {
                    lRet = channel.DoInitialDB(strDbName,
                        out strTempError);
                    if (lRet == -1)
                    {
                        strError += "清除类型为 "+strType+" 的实用库 '" + strDbName + "' 内数据时候发生错误:" + strTempError + "; ";
                    }
                }
            }


            if (String.IsNullOrEmpty(strError) == false)
                return -1;

            return 0;
        }
예제 #32
0
        // SetBiblioInfo() API 或CopyBiblioInfo() API 的恢复动作
        // 函数内,使用return -1;还是goto ERROR1; 要看错误发生的时候,是否还有价值继续探索SnapShot重试。如果是,就用后者。
        /*
<root>
  <operation>setBiblioInfo</operation> 
  <action>...</action> 具体动作 有 new/change/delete/onlydeletebiblio/onlydeletesubrecord 和 onlycopybiblio/onlymovebiblio/copy/move
  <record recPath='中文图书/3'>...</record> 记录体 动作为new/change/ *move* / *copy* 时具有此元素(即delete时没有此元素)
  <oldRecord recPath='中文图书/3'>...</oldRecord> 被覆盖、删除或者移动的记录 动作为change/ *delete* / *move* / *copy* 时具备此元素
  <deletedEntityRecords> 被删除的实体记录(容器)。只有当<action>为delete时才有这个元素。
	  <record recPath='中文图书实体/100'>...</record> 这个元素可以重复。注意元素内文本内容目前为空。
	  ...
  </deletedEntityRecords>
  <copyEntityRecords> 被复制的实体记录(容器)。只有当<action>为*copy*时才有这个元素。
	  <record recPath='中文图书实体/100' targetRecPath='中文图书实体/110'>...</record> 这个元素可以重复。注意元素内文本内容目前为空。recPath属性为源记录路径,targetRecPath为目标记录路径
	  ...
  </copyEntityRecords>
  <moveEntityRecords> 被移动的实体记录(容器)。只有当<action>为*move*时才有这个元素。
	  <record recPath='中文图书实体/100' targetRecPath='中文图书实体/110'>...</record> 这个元素可以重复。注意元素内文本内容目前为空。recPath属性为源记录路径,targetRecPath为目标记录路径
	  ...
  </moveEntityRecords>
  <copyOrderRecords /> <moveOrderRecords />
  <copyIssueRecords /> <moveIssueRecords />
  <copyCommentRecords /> <moveCommentRecords />
  <operator>test</operator> 
  <operTime>Fri, 08 Dec 2006 10:12:20 GMT</operTime> 
</root>

逻辑恢复delete操作的时候,检索出全部下属的实体记录删除。
快照恢复的时候,可以根据operlogdom直接删除记录了path的那些实体记录
         * */
        public int RecoverSetBiblioInfo(
            RmsChannelCollection Channels,
            RecoverLevel level,
            XmlDocument domLog,
            out string strError)
        {
            strError = "";

            // 暂时把Robust当作Logic处理
            if (level == RecoverLevel.Robust)
                level = RecoverLevel.Logic;

            long lRet = 0;
            int nRet = 0;

            RmsChannel channel = Channels.GetChannel(this.WsUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }

            bool bReuse = false;    // 是否能够不顾RecorverLevel状态而重用部分代码

        DO_SNAPSHOT:

            string strAction = DomUtil.GetElementText(domLog.DocumentElement,
                "action");

            // 快照恢复
            if (level == RecoverLevel.Snapshot 
                || bReuse == true)
            {
                byte[] timestamp = null;
                byte[] output_timestamp = null;
                string strOutputPath = "";

                if (strAction == "new" || strAction == "change")
                {
                    XmlNode node = null;
                    string strRecord = DomUtil.GetElementText(domLog.DocumentElement,
                        "record",
                        out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<record>元素";
                        goto ERROR1;
                    }
                    string strRecPath = DomUtil.GetAttr(node, "recPath");

                    // 写书目记录
                    lRet = channel.DoSaveTextRes(strRecPath,
                        strRecord,
                        false,
                        "content,ignorechecktimestamp",
                        timestamp,
                        out output_timestamp,
                        out strOutputPath,
                        out strError);
                    if (lRet == -1)
                    {
                        strError = "写入书目记录 '" + strRecPath + "' 时发生错误: " + strError;
                        return -1;
                    }
                }
                else if (strAction == "onlymovebiblio"
                    || strAction == "onlycopybiblio"
                    || strAction == "move"
                    || strAction == "copy")
                {
                    XmlNode node = null;
                    string strTargetRecord = DomUtil.GetElementText(domLog.DocumentElement,
                        "record",
                        out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<record>元素";
                        goto ERROR1;
                    }
                    string strTargetRecPath = DomUtil.GetAttr(node, "recPath");

                    string strOldRecord = DomUtil.GetElementText(domLog.DocumentElement,
                        "oldRecord",
                        out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<oldRecord>元素";
                        return -1;
                    }
                    string strOldRecPath = DomUtil.GetAttr(node, "recPath");

                    string strMergeStyle = DomUtil.GetElementText(domLog.DocumentElement,
                        "mergeStyle");

                    bool bSourceExist = true;
                    // 观察源记录是否存在
                    {
                        string strMetaData = "";
                        string strXml = "";
                        byte[] temp_timestamp = null;

                        lRet = channel.GetRes(strOldRecPath,
                            out strXml,
                            out strMetaData,
                            out temp_timestamp,
                            out strOutputPath,
                            out strError);
                        if (lRet == -1)
                        {
                            if (channel.ErrorCode == ChannelErrorCode.NotFound)
                            {
                                bSourceExist = false;
                            }
                        }
                    }

                    if (bSourceExist == true)
                    {
                        string strIdChangeList = "";

                        // 复制书目记录
                        lRet = channel.DoCopyRecord(strOldRecPath,
                            strTargetRecPath,
                            strAction == "onlymovebiblio" ? true : false,   // bDeleteSourceRecord
                            strMergeStyle,
                            out strIdChangeList,
                            out output_timestamp,
                            out strOutputPath,
                            out strError);
                        if (lRet == -1)
                        {
                            strError = "DoCopyRecord() error :" + strError;
                            goto ERROR1;
                        }
                    }

                    /*
                    // 写书目记录
                    lRet = channel.DoSaveTextRes(strRecPath,
                        strRecord,
                        false,
                        "content,ignorechecktimestamp",
                        timestamp,
                        out output_timestamp,
                        out strOutputPath,
                        out strError);
                    if (lRet == -1)
                    {
                        strError = "复制书目记录 '" + strOldRecPath + "' 到 '" + strTargetRecPath + "' 时发生错误: " + strError;
                        return -1;
                    }                     * */


                    if (bSourceExist == false)
                    {
                        if (String.IsNullOrEmpty(strTargetRecord) == true)
                        {
                            if (String.IsNullOrEmpty(strOldRecord) == true)
                            {
                                strError = "源记录 '" + strOldRecPath + "' 不存在,并且<record>元素无文本内容,这时<oldRecord>元素也无文本内容,无法获得要写入的记录内容";
                                return -1;
                            }

                            strTargetRecord = strOldRecord;
                        }
                    }

                    // 如果有“新记录”内容
                    if (String.IsNullOrEmpty(strTargetRecord) == false)
                    {

                        // 写书目记录
                        lRet = channel.DoSaveTextRes(strTargetRecPath,
                            strTargetRecord,
                            false,
                            "content,ignorechecktimestamp",
                            timestamp,
                            out output_timestamp,
                            out strOutputPath,
                            out strError);
                        if (lRet == -1)
                        {
                            strError = "写书目记录 '" + strTargetRecPath + "' 时发生错误: " + strError;
                            return -1;
                        }
                    }

                    // 复制或者移动下级子纪录
                    if (strAction == "move"
                    || strAction == "copy")
                    {
                        string[] element_names = new string[] {
                            "copyEntityRecords",
                            "moveEntityRecords",  
                            "copyOrderRecords", 
                            "moveOrderRecords",
                            "copyIssueRecords", 
                            "moveIssueRecords",   
                            "copyCommentRecords", 
                            "moveCommentRecords"     
                        };

                        for (int i = 0; i < element_names.Length; i++)
                        {
                            XmlNode node_subrecords = domLog.DocumentElement.SelectSingleNode(
                                element_names[i]);
                            if (node_subrecords != null)
                            {
                                nRet = CopySubRecords(
                                    channel,
                                    node_subrecords,
                                    strTargetRecPath,
                                    out strError);
                                if (nRet == -1)
                                    return -1;
                            }
                        }

                    }

                    // 2011/12/12
                    if (bSourceExist == true
                        && (strAction == "move" || strAction == "onlymovebiblio")
                        )
                    {
                        int nRedoCount = 0;
                    REDO_DELETE:
                        // 删除源书目记录
                        lRet = channel.DoDeleteRes(strOldRecPath,
                            timestamp,
                            out output_timestamp,
                            out strError);
                        if (lRet == -1)
                        {
                            if (channel.ErrorCode == ChannelErrorCode.NotFound)
                            {
                                // 记录本来就不存在
                            }
                            else if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch)
                            {
                                if (nRedoCount < 10)
                                {
                                    timestamp = output_timestamp;
                                    nRedoCount++;
                                    goto REDO_DELETE;
                                }
                            }
                            else
                            {
                                strError = "删除书目记录 '" + strOldRecPath + "' 时发生错误: " + strError;
                                return -1;
                            }
                        }
                    }
                }
                else if (strAction == "delete"
                    || strAction == "onlydeletebiblio"
                    || strAction == "onlydeletesubrecord")
                {
                    XmlNode node = null;
                    string strOldRecord = DomUtil.GetElementText(domLog.DocumentElement,
                        "oldRecord",
                        out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<oldRecord>元素";
                        return -1;
                    }
                    string strRecPath = DomUtil.GetAttr(node, "recPath");

                    if (strAction != "onlydeletesubrecord")
                    {
                        int nRedoCount = 0;
                    REDO:
                        // 删除书目记录
                        lRet = channel.DoDeleteRes(strRecPath,
                            timestamp,
                            out output_timestamp,
                            out strError);
                        if (lRet == -1)
                        {
                            if (channel.ErrorCode == ChannelErrorCode.NotFound)
                                goto DO_DELETE_CHILD_ENTITYRECORDS;   // 记录本来就不存在
                            if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch)
                            {
                                if (nRedoCount < 10)
                                {
                                    timestamp = output_timestamp;
                                    nRedoCount++;
                                    goto REDO;
                                }
                            }
                            strError = "删除书目记录 '" + strRecPath + "' 时发生错误: " + strError;
                            return -1;
                        }
                    }

                DO_DELETE_CHILD_ENTITYRECORDS:
                    if (strAction == "delete" || strAction == "onlydeletesubrecord")
                    {
                        XmlNodeList nodes = domLog.DocumentElement.SelectNodes("deletedEntityRecords/record");
                        for (int i = 0; i < nodes.Count; i++)
                        {
                            string strEntityRecPath = DomUtil.GetAttr(nodes[i], "recPath");

                            /*
                            if (String.IsNullOrEmpty(strEntityRecPath) == true)
                                continue;
                             * */
                            int nRedoDeleteCount = 0;
                        REDO_DELETE_ENTITY:
                            // 删除实体记录
                            lRet = channel.DoDeleteRes(strEntityRecPath,
                                timestamp,
                                out output_timestamp,
                                out strError);
                            if (lRet == -1)
                            {
                                if (channel.ErrorCode == ChannelErrorCode.NotFound)
                                    continue;   // 记录本来就不存在
                                if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch)
                                {
                                    if (nRedoDeleteCount < 10)
                                    {
                                        timestamp = output_timestamp;
                                        nRedoDeleteCount++;
                                        goto REDO_DELETE_ENTITY;
                                    }
                                }
                                strError = "删除实体记录 '" + strEntityRecPath + "' 时发生错误: " + strError;
                                return -1;
                            }
                        }

                        nodes = domLog.DocumentElement.SelectNodes("deletedOrderRecords/record");
                        for (int i = 0; i < nodes.Count; i++)
                        {
                            string strOrderRecPath = DomUtil.GetAttr(nodes[i], "recPath");

                            if (String.IsNullOrEmpty(strOrderRecPath) == true)
                                continue;
                            int nRedoDeleteCount = 0;
                        REDO_DELETE_ORDER:
                            // 删除订购记录
                            lRet = channel.DoDeleteRes(strOrderRecPath,
                                timestamp,
                                out output_timestamp,
                                out strError);
                            if (lRet == -1)
                            {
                                if (channel.ErrorCode == ChannelErrorCode.NotFound)
                                    continue;   // 记录本来就不存在
                                if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch)
                                {
                                    if (nRedoDeleteCount < 10)
                                    {
                                        timestamp = output_timestamp;
                                        nRedoDeleteCount++;
                                        goto REDO_DELETE_ORDER;
                                    }
                                }
                                strError = "删除订购记录 '" + strOrderRecPath + "' 时发生错误: " + strError;
                                return -1;
                            }
                        }

                        nodes = domLog.DocumentElement.SelectNodes("deletedIssueRecords/record");
                        for (int i = 0; i < nodes.Count; i++)
                        {
                            string strIssueRecPath = DomUtil.GetAttr(nodes[i], "recPath");

                            if (String.IsNullOrEmpty(strIssueRecPath) == true)
                                continue;
                            int nRedoDeleteCount = 0;
                        REDO_DELETE_ISSUE:
                            // 删除期记录
                            lRet = channel.DoDeleteRes(strIssueRecPath,
                                timestamp,
                                out output_timestamp,
                                out strError);
                            if (lRet == -1)
                            {
                                if (channel.ErrorCode == ChannelErrorCode.NotFound)
                                    continue;   // 记录本来就不存在
                                if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch)
                                {
                                    if (nRedoDeleteCount < 10)
                                    {
                                        timestamp = output_timestamp;
                                        nRedoDeleteCount++;
                                        goto REDO_DELETE_ISSUE;
                                    }
                                }
                                strError = "删除期记录 '" + strIssueRecPath + "' 时发生错误: " + strError;
                                return -1;
                            }
                        }

                    } // end if
                }


                return 0;
            }

            // 逻辑恢复或者混合恢复
            if (level == RecoverLevel.Logic
                || level == RecoverLevel.LogicAndSnapshot)
            {
                // 和数据库中已有记录合并,然后保存
                if (strAction == "new" || strAction == "change")
                {
                    // 和SnapShot方式相同
                    bReuse = true;
                    goto DO_SNAPSHOT;
                }
                else if (strAction == "onlymovebiblio"
                    || strAction == "onlycopybiblio"
                    || strAction == "move"
                    || strAction == "copy")
                {
                    // 和SnapShot方式相同
                    bReuse = true;
                    goto DO_SNAPSHOT;
                }
                else if (strAction == "delete"
                    || strAction == "onlydeletebiblio"
                    || strAction == "onlydeletesubrecord")
                {
                    XmlNode node = null;
                    string strOldRecord = DomUtil.GetElementText(domLog.DocumentElement,
                        "oldRecord",
                        out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<oldRecord>元素";
                        return -1;
                    }
                    string strRecPath = DomUtil.GetAttr(node, "recPath");

                    if (strAction != "onlydeletesubrecord")
                    {
                        int nRedoCount = 0;
                        byte[] timestamp = null;
                        byte[] output_timestamp = null;
                    REDO:
                        // 删除书目记录
                        lRet = channel.DoDeleteRes(strRecPath,
                            timestamp,
                            out output_timestamp,
                            out strError);
                        if (lRet == -1)
                        {
                            if (channel.ErrorCode == ChannelErrorCode.NotFound)
                                goto DO_DELETE_CHILD_ENTITYRECORDS;   // 记录本来就不存在
                            if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch)
                            {
                                if (nRedoCount < 10)
                                {
                                    timestamp = output_timestamp;
                                    nRedoCount++;
                                    goto REDO;
                                }
                            }
                            strError = "删除书目记录 '" + strRecPath + "' 时发生错误: " + strError;
                            goto ERROR1;
                        }
                    }

                DO_DELETE_CHILD_ENTITYRECORDS:

                    if (strAction == "delete" || strAction == "onlydeletesubrecord")
                    {
                        // 删除属于同一书目记录的全部实体记录
                        // return:
                        //      -1  error
                        //      0   没有找到属于书目记录的任何实体记录,因此也就无从删除
                        //      >0  实际删除的实体记录数
                        nRet = DeleteBiblioChildEntities(channel,
                            strRecPath,
                            null,
                            out strError);
                        if (nRet == -1)
                        {
                            strError = "删除书目记录 '" + strRecPath + "' 下属的实体记录时出错: " + strError;
                            goto ERROR1;
                        }

                        // return:
                        //      -1  error
                        //      0   没有找到属于书目记录的任何实体记录,因此也就无从删除
                        //      >0  实际删除的实体记录数
                        nRet = this.OrderItemDatabase.DeleteBiblioChildItems(
                            // Channels,
                            channel,
                            strRecPath,
                            null,
                            out strError);
                        if (nRet == -1)
                        {
                            strError = "删除书目记录 '" + strRecPath + "' 下属的订购记录时出错: " + strError;
                            goto ERROR1;
                        }

                        // return:
                        //      -1  error
                        //      0   没有找到属于书目记录的任何实体记录,因此也就无从删除
                        //      >0  实际删除的实体记录数
                        nRet = this.IssueItemDatabase.DeleteBiblioChildItems(
                            // Channels,
                            channel,
                            strRecPath,
                            null,
                            out strError);
                        if (nRet == -1)
                        {
                            strError = "删除书目记录 '" + strRecPath + "' 下属的期记录时出错: " + strError;
                            goto ERROR1;
                        }
                    }
                }
                else
                {
                    strError = "无法识别的<action>内容 '" + strAction + "'";
                    return -1;
                }
            }
            return 0;
        ERROR1:
            if (level == RecoverLevel.LogicAndSnapshot)
            {
                level = RecoverLevel.Snapshot;
                goto DO_SNAPSHOT;
            }
            return -1;
        }
예제 #33
0
파일: Util.cs 프로젝트: renyh1013/dp2
        /// <summary>
        /// 检索实用库
        /// </summary>
        /// <param name="Channels"></param>
        /// <param name="strServerUrl"></param>
        /// <param name="strDbName"></param>
        /// <param name="strFrom"></param>
        /// <param name="strKey"></param>
        /// <param name="strValueAttrName"></param>
        /// <param name="strValue"></param>
        /// <param name="strError"></param>
        /// <returns></returns>
        public static int SearchUtilDb(
            RmsChannelCollection Channels,
            string strServerUrl,
            string strDbName,
            string strFrom,
            string strKey,
            string strValueAttrName,
            out string strValue,
            out string strError)
        {
            strError = "";
            strValue = "";

            string strPath = "";

            RmsChannel channel = Channels.GetChannel(strServerUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }

            int nRet = SearchOnePath(channel,
                strDbName,
                strFrom,
                strKey,
                out strPath,
                out strError);
            if (nRet == -1)
                return -1;
            if (nRet == 0)
                return 0;


            // 取记录
            string strStyle = "content,data,timestamp";

            string strMetaData;
            string strOutputPath;
            string strXml = "";
            byte[] baTimeStamp = null;

            long lRet = channel.GetRes(strPath,
                strStyle,
                out strXml,
                out strMetaData,
                out baTimeStamp,
                out strOutputPath,
                out strError);
            if (lRet == -1)
            {
                strError = "检索 '" + strPath + "' 记录体时出错: " + strError;
                return -1;
            }


            XmlDocument domRecord = new XmlDocument();
            try
            {
                domRecord.LoadXml(strXml);
            }
            catch (Exception ex)
            {
                strError = "装载路径为'" + strPath + "'的xml记录时出错: " + ex.Message;
                return -1;
            }

            strValue = DomUtil.GetAttr(domRecord.DocumentElement, strValueAttrName);

            return 1;
        }
예제 #34
0
        /*
foregift 创建押金记录

API: Foregift()

<root>
  <operation>foregift</operation> 操作类型
  <action>...</action> 具体动作 目前有foregift return (注: return操作时,overdue元素里面的price属性,可以使用宏 %return_foregift_price% 表示当前剩余的押金额)
  <readerBarcode>R0000002</readerBarcode> 读者证条码号
  <operator>test</operator> 操作者
  <operTime>Fri, 08 Dec 2006 04:17:45 GMT</operTime> 操作时间
  <overdues>...</overdues> 押金信息 通常内容为一个字符串,为一个或多个<overdue>元素XML文本片断
  <readerRecord recPath='...'>...</readerRecord>	最新读者记录
</root>
         * * */
        public int RecoverForegift(
            RmsChannelCollection Channels,
            RecoverLevel level,
            XmlDocument domLog,
            out string strError)
        {
            strError = "";

            // 暂时把Robust当作Logic处理
            if (level == RecoverLevel.Robust)
                level = RecoverLevel.Logic;


            long lRet = 0;
            int nRet = 0;

            RmsChannel channel = Channels.GetChannel(this.WsUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }

        DO_SNAPSHOT:

            // 快照恢复
            if (level == RecoverLevel.Snapshot)
            {
                XmlNode node = null;
                string strReaderXml = DomUtil.GetElementText(domLog.DocumentElement,
                    "readerRecord",
                    out node);
                if (node == null)
                {
                    strError = "日志记录中缺<readerRecord>元素";
                    return -1;
                }
                string strReaderRecPath = DomUtil.GetAttr(node, "recPath");

                byte[] timestamp = null;
                byte[] output_timestamp = null;
                string strOutputPath = "";

                // 写读者记录
                lRet = channel.DoSaveTextRes(strReaderRecPath,
                    strReaderXml,
                    false,
                    "content,ignorechecktimestamp",
                    timestamp,
                    out output_timestamp,
                    out strOutputPath,
                    out strError);
                if (lRet == -1)
                {
                    strError = "写入读者记录 '" + strReaderRecPath + "' 时发生错误: " + strError;
                    return -1;
                }

                return 0;
            }


            // 逻辑恢复或者混合恢复
            if (level == RecoverLevel.Logic
                || level == RecoverLevel.LogicAndSnapshot)
            {
                // string strRecoverComment = "";

                string strAction = DomUtil.GetElementText(domLog.DocumentElement,
                    "action");

                string strReaderBarcode = DomUtil.GetElementText(domLog.DocumentElement,
                    "readerBarcode");
                ///
                if (String.IsNullOrEmpty(strReaderBarcode) == true)
                {
                    strError = "日志记录中<readerBarcode>元素值为空";
                    goto ERROR1;
                }

                string strOperator = DomUtil.GetElementText(domLog.DocumentElement,
                    "operator");

                string strOperTime = DomUtil.GetElementText(domLog.DocumentElement,
                    "operTime");

                string strOverdues = DomUtil.GetElementText(domLog.DocumentElement,
                    "overdues");
                if (String.IsNullOrEmpty(strOverdues) == true)
                {
                    strError = "日志记录中<overdues>元素值为空";
                    goto ERROR1;
                }

                // 从overdues字符串中分析出id
                XmlDocument tempdom = new XmlDocument();
                tempdom.LoadXml("<root />");
                XmlDocumentFragment fragment = tempdom.CreateDocumentFragment();
                fragment.InnerXml = strOverdues;
                tempdom.DocumentElement.AppendChild(fragment);

                XmlNode tempnode = tempdom.DocumentElement.SelectSingleNode("overdue");
                if (tempnode == null)
                {
                    strError = "<overdues>元素内容有误,缺乏<overdue>元素";
                    goto ERROR1;
                }

                string strID = DomUtil.GetAttr(tempnode, "id");
                if (String.IsNullOrEmpty(strID) == true)
                {
                    strError = "日志记录中<overdues>内容中<overdue>元素中id属性值为空";
                    goto ERROR1;
                }

                // 读入读者记录
                string strReaderXml = "";
                string strOutputReaderRecPath = "";
                byte[] reader_timestamp = null;

                nRet = this.GetReaderRecXml(
                    // Channels,
                    channel,
                    strReaderBarcode,
                    out strReaderXml,
                    out strOutputReaderRecPath,
                    out reader_timestamp,
                    out strError);
                if (nRet == 0)
                {
                    strError = "读者证条码号 '" + strReaderBarcode + "' 不存在";
                    goto ERROR1;
                }
                if (nRet == -1)
                {
                    strError = "读入证条码号为 '" + strReaderBarcode + "' 的读者记录时发生错误: " + strError;
                    goto ERROR1;
                }

                XmlDocument readerdom = null;
                nRet = LibraryApplication.LoadToDom(strReaderXml,
                    out readerdom,
                    out strError);
                if (nRet == -1)
                {
                    strError = "装载读者记录进入XML DOM时发生错误: " + strError;
                    goto ERROR1;
                }


                // 
                string strOverdueString = "";
                // 根据Foregift() API要求,修改readerdom
                nRet = DoForegift(strAction,
                    readerdom,
                    ref strID,
                    strOperator,
                    strOperTime,
                    out strOverdueString,
                    out strError);
                if (nRet == -1)
                    goto ERROR1;

                // 写回读者、册记录
                byte[] output_timestamp = null;
                string strOutputPath = "";


                // 写回读者记录
                lRet = channel.DoSaveTextRes(strOutputReaderRecPath,
                    readerdom.OuterXml,
                    false,
                    "content,ignorechecktimestamp",
                    reader_timestamp,
                    out output_timestamp,
                    out strOutputPath,
                    out strError);
                if (lRet == -1)
                    goto ERROR1;


            }


            return 0;
        ERROR1:
            if (level == RecoverLevel.LogicAndSnapshot)
            {
                level = RecoverLevel.Snapshot;
                goto DO_SNAPSHOT;
            }
            return -1;
        }
예제 #35
0
파일: Util.cs 프로젝트: renyh1013/dp2
        /// <summary>
        /// 写入实用库
        /// </summary>
        /// <param name="Channels"></param>
        /// <param name="strServerUrl"></param>
        /// <param name="strDbName"></param>
        /// <param name="strFrom"></param>
        /// <param name="strRootElementName"></param>
        /// <param name="strKeyAttrName"></param>
        /// <param name="strValueAttrName"></param>
        /// <param name="strKey"></param>
        /// <param name="strValue"></param>
        /// <param name="strError"></param>
        /// <returns></returns>
        public static int WriteUtilDb(
            RmsChannelCollection Channels,
            string strServerUrl,
            string strDbName,
            string strFrom,
            string strRootElementName,
            string strKeyAttrName,
            string strValueAttrName,
            string strKey,
            string strValue,
            out string strError)
        {
            strError = "";

            string strPath = "";

            RmsChannel channel = Channels.GetChannel(strServerUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }


            int nRet = SearchOnePath(channel,
                strDbName,
                strFrom,
                strKey,
                out strPath,
                out strError);
            if (nRet == -1)
                return -1;

            string strXml = "";

            if (nRet == 0)
            {
                strPath = strDbName + "/?";
                strXml = "<" + strRootElementName + " " + strKeyAttrName + "='" + strKey + "' " + strValueAttrName + "='" + strValue + "'/>";

                //bNewRecord = true;

            }
            else
            {
                string strPartXml = "/xpath/<locate>@" + strValueAttrName + "</locate><create>@" + strValueAttrName + "</create>";
                strPath += strPartXml;
                strXml = strValue;

                //bNewRecord = false;
            }

            byte[] baTimestamp = null;

            byte[] baOutputTimeStamp = null;
            string strOutputPath = "";

        REDO:


            channel = Channels.GetChannel(strServerUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }



            long lRet = channel.DoSaveTextRes(strPath,
                strXml,
                false,	// bInlucdePreamble
                "ignorechecktimestamp",	// style
                baTimestamp,
                out baOutputTimeStamp,
                out strOutputPath,
                out strError);
            if (lRet == -1)
            {
                if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch)
                {

                    baTimestamp = baOutputTimeStamp;
                    goto REDO;
                }

                return -1;
            }


            return 1;
        }
예제 #36
0
        /*
settlement 结算违约金

API: Settlement()

<root>
  <operation>settlement</operation> 操作类型
  <action>...</action> 具体动作 有settlement undosettlement delete 3种
  <id>1234567-1</id> ID
  <operator>test</operator> 操作者
  <operTime>Fri, 08 Dec 2006 04:17:45 GMT</operTime> 操作时间
  
  <oldAmerceRecord recPath='...'>...</oldAmerceRecord>	旧违约金记录
  <amerceRecord recPath='...'>...</amerceRecord>	新违约金记录 delete操作无此元素
</root>
         * */
        public int RecoverSettlement(
            RmsChannelCollection Channels,
            RecoverLevel level,
            XmlDocument domLog,
            out string strError)
        {
            strError = "";

            // 暂时把Robust当作Logic处理
            if (level == RecoverLevel.Robust)
                level = RecoverLevel.Logic;

            long lRet = 0;
            int nRet = 0;

            RmsChannel channel = Channels.GetChannel(this.WsUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }

        DO_SNAPSHOT:

            // 快照恢复
            if (level == RecoverLevel.Snapshot)
            {
                string strAction = DomUtil.GetElementText(domLog.DocumentElement,
                    "action");

                if (strAction == "settlement"
                    || strAction == "undosettlement")
                {

                    XmlNode node = null;
                    string strAmerceXml = DomUtil.GetElementText(domLog.DocumentElement,
                        "amerceRecord",
                        out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<amerceRecord>元素";
                        return -1;
                    }
                    string strAmerceRecPath = DomUtil.GetAttr(node, "recPath");

                    byte[] timestamp = null;
                    byte[] output_timestamp = null;
                    string strOutputPath = "";

                    // 写违约金记录
                    lRet = channel.DoSaveTextRes(strAmerceRecPath,
                        strAmerceXml,
                        false,
                        "content,ignorechecktimestamp",
                        timestamp,
                        out output_timestamp,
                        out strOutputPath,
                        out strError);
                    if (lRet == -1)
                    {
                        strError = "写入违约金记录 '" + strAmerceRecPath + "' 时发生错误: " + strError;
                        return -1;
                    }

                }
                else if (strAction == "delete")
                {
                    XmlNode node = null;
                    string strOldAmerceXml = DomUtil.GetElementText(domLog.DocumentElement,
                        "oldAmerceRecord",
                        out node);
                    if (node == null)
                    {
                        strError = "日志记录中缺<oldAmerceRecord>元素";
                        return -1;
                    }
                    string strOldAmerceRecPath = DomUtil.GetAttr(node, "recPath");

                    // 删除违约金记录
                    int nRedoCount = 0;
                    byte[] timestamp = null;
                    byte[] output_timestamp = null;

                REDO_DELETE:
                    lRet = channel.DoDeleteRes(strOldAmerceRecPath,
                        timestamp,
                        out output_timestamp,
                        out strError);
                    if (lRet == -1)
                    {
                        if (channel.ErrorCode == ChannelErrorCode.NotFound)
                            return 0;   // 记录本来就不存在

                        if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch)
                        {
                            if (nRedoCount < 10)
                            {
                                timestamp = output_timestamp;
                                nRedoCount++;
                                goto REDO_DELETE;
                            }
                        }
                        strError = "删除违约金记录 '" + strOldAmerceRecPath + "' 时发生错误: " + strError;
                        return -1;

                    }
                }
                else
                {
                    strError = "未能识别的action值 '" + strAction + "'";
                }

                return 0;
            }

            // 逻辑恢复或者混合恢复
            if (level == RecoverLevel.Logic
                || level == RecoverLevel.LogicAndSnapshot)
            {
                string strAction = DomUtil.GetElementText(domLog.DocumentElement,
                    "action");

                string strID = DomUtil.GetElementText(domLog.DocumentElement,
                    "id");

                ///
                if (String.IsNullOrEmpty(strID) == true)
                {
                    strError = "日志记录中<id>元素值为空";
                    goto ERROR1;
                }

                string strOperator = DomUtil.GetElementText(domLog.DocumentElement,
                    "operator");

                string strOperTime = DomUtil.GetElementText(domLog.DocumentElement,
                    "operTime");

                // 通过id获得违约金记录的路径
                string strText = "";
                string strCount = "";

                strCount = "<maxCount>100</maxCount>";

                strText = "<item><word>"
    + StringUtil.GetXmlStringSimple(strID)
    + "</word>"
    + strCount
    + "<match>exact</match><relation>=</relation><dataType>string</dataType>"
    + "</item>";
                string strQueryXml = "<target list='"
                    + StringUtil.GetXmlStringSimple(this.AmerceDbName + ":" + "ID")       // 2007/9/14
                    + "'>" + strText
    + "<lang>zh</lang></target>";

                lRet = channel.DoSearch(strQueryXml,
                    "amerced",
                    "", // strOuputStyle
                    out strError);
                if (lRet == -1)
                {
                    strError = "检索ID为 '" + strID + "' 的违约金记录出错: " + strError;
                    goto ERROR1;
                }

                if (lRet == 0)
                {
                    strError = "没有找到id为 '" + strID + "' 的违约金记录";
                    goto ERROR1;
                }

                List<string> aPath = null;
                lRet = channel.DoGetSearchResult(
                    "amerced",   // strResultSetName
                    0,
                    1,
                    "zh",
                    null,   // stop
                    out aPath,
                    out strError);
                if (lRet == -1)
                    goto ERROR1;

                if (lRet == 0)
                {
                    strError = "获取结果集未命中";
                    goto ERROR1;
                }

                if (aPath.Count != 1)
                {
                    strError = "aPath.Count != 1";
                    goto ERROR1;
                }

                string strAmerceRecPath = aPath[0];

                // 结算一个交费记录
                // parameters:
                //      bCreateOperLog  是否创建日志
                //      strOperTime 结算的操作时间
                //      strOperator 结算的操作者
                // return:
                //      -2  致命出错,不宜再继续循环调用本函数
                //      -1  一般出错,可以继续循环调用本函数
                //      0   正常
                nRet = SettlementOneRecord(
                    "", // 确保可以执行
                    false,  // 不创建日志
                    channel,
                    strAction,
                    strAmerceRecPath,
                    strOperTime,
                    strOperator,
                    "", // 表示本机触发
                    out strError);
                if (nRet == -1 || nRet == -2)
                    goto ERROR1;

            }


            return 0;
        ERROR1:
            if (level == RecoverLevel.LogicAndSnapshot)
            {
                level = RecoverLevel.Snapshot;
                goto DO_SNAPSHOT;
            }
            return -1;
        }