Esempio n. 1
0
        // 解码Present请求包
        public static int Decode_PresentRequest(
            BerNode root,
            out PresentRequestInfo info,
            out string strError)
        {
            strError = "";

            int nRet = 0;

            info = new PresentRequestInfo();

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

            if (root.m_uTag != BerTree.z3950_presentRequest)
            {
                strError = "root tag is not z3950_presentRequest";
                return -1;
            }

            for (int i = 0; i < root.ChildrenCollection.Count; i++)
            {
                BerNode node = root.ChildrenCollection[i];

                switch (node.m_uTag)
                {
                    case BerTree.z3950_ReferenceId: // 2
                        info.m_strReferenceId = node.GetCharNodeData();
                        break;
                    case BerTree.z3950_ResultSetId: // 31 resultSetId (IntenationalString)
                        info.m_strResultSetID = node.GetCharNodeData();
                        break;
                    case BerTree.z3950_resultSetStartPoint: // 30 resultSetStartPoint  (Integer)         
                        info.m_lResultSetStartPoint = node.GetIntegerNodeData();
                        break;
                    case BerTree.z3950_numberOfRecordsRequested: // 29 numberOfRecordsRequested (Integer)      
                        info.m_lNumberOfRecordsRequested = node.GetIntegerNodeData();
                        break;
                    case BerTree.z3950_ElementSetNames: // 19 ElementSetNames (complicates)
                        {
                            List<string> elementset_names = null;
                            nRet = DecodeElementSetNames(node,
                                out elementset_names,
                                out strError);
                            if (nRet == -1)
                                return -1;

                            info.m_elementSetNames = elementset_names;
                        }
                        break;
                    default:
                        break;
                }
            }

            return 0;
        }
Esempio n. 2
0
        // 编码(构造) Present响应包
        int Encode_PresentResponse(PresentRequestInfo info,
            out byte[] baPackage)
        {
            baPackage = null;
            int nRet = 0;
            string strError = "";

            DiagFormat diag = null;

            BerTree tree = new BerTree();
            BerNode root = null;

            string strResultSetName = info.m_strResultSetID;
            if (String.IsNullOrEmpty(strResultSetName) == true)
                strResultSetName = "default";
            long lStart = info.m_lResultSetStartPoint - 1;
            long lNumber = info.m_lNumberOfRecordsRequested;

            long lPerCount = lNumber;

            long lHitCount = 0;

            List<string> paths = new List<string>();

            int nPresentStatus = 5; // failed

            // 获取结果集中需要部分的记录path
            long lOffset = lStart;
            int nCount = 0;
            for (; ; )
            {
                DigitalPlatform.LibraryClient.localhost.Record[] searchresults = null;

                long lRet = this._channel.GetSearchResult(
                    null,   // stop,
                    strResultSetName,   // strResultSetName
                    lOffset,
                    lPerCount,
                    "id",
                    "zh",   // this.Lang,
                    out searchresults,
                    out strError);
                /*
                // 测试获取结果集失败的情况,返回非代理诊断记录
                lRet = -1;
                strError = "测试检索错误信息!";
                 * */

                if (lRet == -1)
                {
                    SetPresentDiagRecord(ref diag,
                        2,  // temporary system error
                        strError);
                    break;
                }
                if (lRet == 0)
                {
                    // goto ERROR1 ?
                }

                lHitCount = lRet;   // 顺便得到命中记录总条数

                // 转储
                for (int i = 0; i < searchresults.Length; i++)
                {
                    paths.Add(searchresults[i].Path);
                }

                lOffset += searchresults.Length;
                lPerCount -= searchresults.Length;
                nCount += searchresults.Length;

                if (lOffset >= lHitCount
                    || lPerCount <= 0
                    || nCount >= lNumber)
                {
                    // 
                    break;
                }
            }

            // TODO: 需要注意多个错误是否形成多个diag记录?V2不允许这样,V3允许这样
            if (lHitCount < info.m_lResultSetStartPoint
                && diag == null)
            {
                strError = "start参数值 "
                    + info.m_lResultSetStartPoint
                    + " 超过结果集中记录总数 "
                    + lHitCount;
                // return -1;  // 如果表示错误状态?
                SetPresentDiagRecord(ref diag,
                    13,  // Present request out-of-range
                    strError);
            }

            int MAX_PRESENT_RECORD = 100;

            // 限制每次 present 的记录数量
            if (lNumber > MAX_PRESENT_RECORD)
                lNumber = MAX_PRESENT_RECORD;

            long nNextResultSetPosition = 0;

            // 
            if (lHitCount < (lStart - 1) + lNumber)
            {
                // 是 present 错误,但还可以调整 lNumber
                lNumber = lHitCount - (lStart - 1);
                nNextResultSetPosition = 0;
            }
            else
            {
                //
                nNextResultSetPosition = lStart + lNumber + 1;
            }

            root = tree.m_RootNode.NewChildConstructedNode(
                BerTree.z3950_presentResponse,
                BerNode.ASN1_CONTEXT);

            // reference id
            if (String.IsNullOrEmpty(info.m_strReferenceId) == false)
            {
                root.NewChildCharNode(BerTree.z3950_ReferenceId,
                    BerNode.ASN1_CONTEXT,
                    Encoding.UTF8.GetBytes(info.m_strReferenceId));
            }

            List<RetrivalRecord> records = new List<RetrivalRecord>();

            // 获取要返回的MARC记录
            if (diag == null)
            {

                // 记录编码格式为 GRS-1 (generic-record-syntax-1) :
                //		EXTERNAL 
                //			--- OID (Object Identifier)
                //			--- MARC (OCTET STRING)
                //	m_strOID = _T("1.2.840.10003.5.1");  // OID of UNIMARC
                //	m_strOID = _T("1.2.840.10003.5.10"); // OID of USMARC //
                // 需要建立一个数据库名和oid的对照表,方面快速取得数据库MARC syntax OID

                // TODO: 编码过程中,可能会发现记录太多,总尺寸超过Initial中规定的prefered message size。
                // 这样需要减少返回的记录数量。这样,就需要先做这里的循环,后构造另外几个参数
                int nSize = 0;
                for (int i = 0; i < (int)lNumber; i++)
                {
                    // 编码 N 条 MARC 记录
                    //
                    // if (m_bStop) return false;

                    // 取出数据库指针
                    // lStart 不是 0 起点的
                    string strPath = paths[i];

                    // 解析出数据库名和ID
                    string strDbName = Global.GetDbName(strPath);
                    string strRecID = Global.GetRecordID(strPath);

                    // 如果取得的是xml记录,则根元素可以看出记录的marc syntax,进一步可以获得oid;
                    // 如果取得的是MARC格式记录,则需要根据数据库预定义的marc syntax来看出oid了
                    string strMarcSyntaxOID = GetMarcSyntaxOID(strDbName);

                    byte[] baMARC = null;

                    RetrivalRecord record = new RetrivalRecord();
                    record.m_strDatabaseName = strDbName;

                    // 根据书目库名获得书目库属性对象
                    BiblioDbProperty prop = this._service.GetDbProperty(
                        strDbName,
                        false);

                    nRet = GetMARC(strPath,
                        info.m_elementSetNames,
                        prop != null ? prop.AddField901 : false,
                        out baMARC,
                        out strError);

                    /*
                    // 测试记录群中包含诊断记录
                    if (i == 1)
                    {
                        nRet = -1;
                        strError = "测试获取记录错误";
                    }*/
                    if (nRet == -1)
                    {
                        record.m_surrogateDiagnostic = new DiagFormat();
                        record.m_surrogateDiagnostic.m_strDiagSetID = "1.2.840.10003.4.1";
                        record.m_surrogateDiagnostic.m_nDiagCondition = 14;  // system error in presenting records
                        record.m_surrogateDiagnostic.m_strAddInfo = strError;
                    }
                    else if (nRet == 0)
                    {
                        record.m_surrogateDiagnostic = new DiagFormat();
                        record.m_surrogateDiagnostic.m_strDiagSetID = "1.2.840.10003.4.1";
                        record.m_surrogateDiagnostic.m_nDiagCondition = 1028;  // record deleted
                        record.m_surrogateDiagnostic.m_strAddInfo = strError;
                    }
                    else if (String.IsNullOrEmpty(strMarcSyntaxOID) == true)
                    {
                        // 根据数据库名无法获得marc syntax oid。可能是虚拟库检索命中记录所在的物理库没有在dp2zserver.xml中配置。
                        record.m_surrogateDiagnostic = new DiagFormat();
                        record.m_surrogateDiagnostic.m_strDiagSetID = "1.2.840.10003.4.1";
                        record.m_surrogateDiagnostic.m_nDiagCondition = 109;  // database unavailable // 似乎235:database dos not exist也可以
                        record.m_surrogateDiagnostic.m_strAddInfo = "根据数据库名 '" + strDbName + "' 无法获得marc syntax oid";
                    }
                    else
                    {
                        record.m_external = new External();
                        record.m_external.m_strDirectRefenerce = strMarcSyntaxOID;
                        record.m_external.m_octectAligned = baMARC;
                    }

                    nSize += record.GetPackageSize();

                    if (i == 0)
                    {
                        // 连一条记录也放不下
                        if (nSize > this._lExceptionalRecordSize)
                        {
                            Debug.Assert(diag == null, "");
                            SetPresentDiagRecord(ref diag,
                                17, // record exceeds Exceptional_record_size
                                "记录尺寸 " + nSize.ToString() + " 超过 Exceptional_record_size " + this._lExceptionalRecordSize.ToString());
                            lNumber = 0;
                            break;
                        }
                    }
                    else
                    {
                        if (nSize >= this._lPreferredMessageSize)
                        {
                            // 调整返回的记录数
                            lNumber = i;
                            break;
                        }
                    }

                    records.Add(record);
                }
            }


            // numberOfRecordsReturned
            root.NewChildIntegerNode(BerTree.z3950_NumberOfRecordsReturned, // 24
                BerNode.ASN1_CONTEXT,   // ASN1_PRIMITIVE BUG!!!
                BitConverter.GetBytes((long)lNumber));

            if (diag != null)
                nPresentStatus = 5;
            else
                nPresentStatus = 0;

            // nextResultSetPosition
            // if 0, that's end of the result set
            // else M+1, M is 最后一次 present response 的最后一条记录在 result set 中的 position
            root.NewChildIntegerNode(BerTree.z3950_NextResultSetPosition, // 25
                BerNode.ASN1_CONTEXT,   // ASN1_PRIMITIVE BUG!!!
                BitConverter.GetBytes((long)nNextResultSetPosition));

            // presentStatus
            // success      (0),
            // partial-1    (1),
            // partial-2    (2),
            // partial-3    (3),
            // partial-4    (4),
            // failure      (5).
            root.NewChildIntegerNode(BerTree.z3950_presentStatus, // 27
                BerNode.ASN1_CONTEXT,   // ASN1_PRIMITIVE BUG!!!
               BitConverter.GetBytes((long)nPresentStatus));


            // 诊断记录
            if (diag != null)
            {
                BerNode nodeDiagRoot = root.NewChildConstructedNode(BerTree.z3950_nonSurrogateDiagnostic,    // 130
                    BerNode.ASN1_CONTEXT);

                diag.BuildBer(nodeDiagRoot);

                /*
                nodeDiagRoot.NewChildOIDsNode(6,
                    BerNode.ASN1_UNIVERSAL,
                    diag.m_strDiagSetID);   // "1.2.840.10003.4.1"

                nodeDiagRoot.NewChildIntegerNode(2,
                    BerNode.ASN1_UNIVERSAL,
                    BitConverter.GetBytes((long)diag.m_nDiagCondition));

                if (String.IsNullOrEmpty(diag.m_strAddInfo) == false)
                {
                    nodeDiagRoot.NewChildCharNode(26,
                        BerNode.ASN1_UNIVERSAL,
                        Encoding.UTF8.GetBytes(diag.m_strAddInfo));
                }
                 * */
            }


            // 如果 present 是非法的,到这里打包完成,可以返回了
            if (0 != nPresentStatus)
                goto END1;

            // 编码记录BER树

            // 以下为 present 成功时,打包返回记录。
            // present success
            // presRoot records child, constructed (choice of ... ... optional)
            // if present fail, then may be no records 'node'
            // Records ::= CHOICE {
            //		responseRecords              [28]   IMPLICIT SEQUENCE OF NamePlusRecord,
            //		nonSurrogateDiagnostic       [130]  IMPLICIT DefaultDiagFormat,
            //		multipleNonSurDiagnostics    [205]  IMPLICIT SEQUENCE OF DiagRec} 

            // 当 present 成功时,response 选择了 NamePlusRecord (数据库名 + 记录)
            BerNode node = root.NewChildConstructedNode(BerTree.z3950_dataBaseOrSurDiagnostics,    // 28
                            BerNode.ASN1_CONTEXT);

            for (int i = 0; i < records.Count; i++)
            {
                RetrivalRecord record = records[i];

                record.BuildNamePlusRecord(node);
            }

        END1:

            baPackage = null;
            root.EncodeBERPackage(ref baPackage);

            return 0;
        }