Fix for no preferredSyntax Set
[yazpp-moved-to-github.git] / src / yaz-z-cache.cpp
1 /*
2  * Copyright (c) 2002-2003, Index Data.
3  * See the file LICENSE for details.
4  * 
5  * $Id: yaz-z-cache.cpp,v 1.4 2003-08-28 18:46:54 adam Exp $
6  */
7
8 #include <yaz/log.h>
9 #include <yaz++/proxy.h>
10
11 struct Yaz_RecordCache_Entry {
12     int m_offset;
13     Z_NamePlusRecord *m_record;
14     Z_RecordComposition *m_comp;
15     Yaz_RecordCache_Entry *m_next;
16 };
17
18 Yaz_RecordCache::Yaz_RecordCache ()
19 {
20     m_mem = nmem_create();
21     m_entries = 0;
22     m_presentRequest = 0;
23     m_searchRequest = 0;
24 }
25
26 Yaz_RecordCache::~Yaz_RecordCache ()
27 {
28     nmem_destroy(m_mem);
29 }
30
31 void Yaz_RecordCache::clear ()
32 {
33     nmem_destroy(m_mem);
34     m_mem = nmem_create();
35     m_entries = 0;
36     m_presentRequest = 0;
37     m_searchRequest = 0;
38 }
39
40 void Yaz_RecordCache::copy_searchRequest(Z_SearchRequest *sr)
41 {
42     ODR encode = odr_createmem(ODR_ENCODE);
43     ODR decode = odr_createmem(ODR_DECODE);
44
45     m_searchRequest = 0;
46     m_presentRequest = 0;
47     int v = z_SearchRequest (encode, &sr, 1, 0);
48     if (v)
49     {
50         int len;
51         char *buf = odr_getbuf(encode, &len, 0);
52         odr_setbuf(decode, buf, len, 0);
53         z_SearchRequest(decode, &m_searchRequest, 1, 0);
54         nmem_transfer(m_mem, decode->mem);
55     }
56     odr_destroy(encode);
57     odr_destroy(decode);
58 }
59
60 void Yaz_RecordCache::copy_presentRequest(Z_PresentRequest *pr)
61 {
62     ODR encode = odr_createmem(ODR_ENCODE);
63     ODR decode = odr_createmem(ODR_DECODE);
64     
65     m_searchRequest = 0;
66     m_presentRequest = 0;
67     int v = z_PresentRequest (encode, &pr, 1, 0);
68     if (v)
69     {
70         int len;
71         char *buf = odr_getbuf(encode, &len, 0);
72         odr_setbuf(decode, buf, len, 0);
73         z_PresentRequest(decode, &m_presentRequest, 1, 0);
74         nmem_transfer(m_mem, decode->mem);
75     }
76     odr_destroy(encode);
77     odr_destroy(decode);
78 }
79
80 void Yaz_RecordCache::add (ODR o, Z_NamePlusRecordList *npr, int start,
81                            int hits)
82 {
83     // Build appropriate compspec for this response
84     Z_RecordComposition *comp = 0;
85     if (hits == -1 && m_presentRequest)
86         comp = m_presentRequest->recordComposition;
87     else if (hits > 0 && m_searchRequest)
88     {
89         Z_ElementSetNames *esn;
90
91         if (hits <= *m_searchRequest->smallSetUpperBound)
92             esn = m_searchRequest->smallSetElementSetNames;
93         else
94             esn = m_searchRequest->mediumSetElementSetNames;
95         comp = (Z_RecordComposition *) nmem_malloc(m_mem, sizeof(*comp));
96         comp->which = Z_RecordComp_simple;
97         comp->u.simple = esn;
98     }
99
100     // Z_NamePlusRecordList *npr to be owned by m_mem..
101     NMEM tmp_mem = odr_extract_mem(o);
102     nmem_transfer(m_mem, tmp_mem);
103     nmem_destroy(tmp_mem);
104     
105     // Insert individual records in cache
106     int i;
107     for (i = 0; i<npr->num_records; i++)
108     {
109         Yaz_RecordCache_Entry *entry = (Yaz_RecordCache_Entry *)
110             nmem_malloc(m_mem, sizeof(*entry));
111         entry->m_record = npr->records[i];
112         entry->m_comp = comp;
113         entry->m_offset = i + start;
114         entry->m_next = m_entries;
115         m_entries = entry;
116     }
117 }
118
119 int Yaz_RecordCache::match (Yaz_RecordCache_Entry *entry,
120                             Odr_oid *syntax, int offset,
121                             Z_RecordComposition *comp)
122 {
123     // See if our compspec match...
124     int match = 0;
125     ODR o1 = odr_createmem(ODR_ENCODE);
126     ODR o2 = odr_createmem(ODR_ENCODE);
127     
128     z_RecordComposition(o1, &comp, 1, 0);
129     z_RecordComposition(o2, &entry->m_comp, 1, 0);
130
131     int len1 = -1;
132     char *buf1 = odr_getbuf(o1, &len1, 0);
133     int len2 = -1;
134     char *buf2 = odr_getbuf(o2, &len2, 0);
135     
136     if (buf1 && buf2 && len1 && len1 == len2 && !memcmp(buf1, buf2, len1))
137         match = 1;
138     else if (!buf1 && !buf2 && !len1 && !len2)
139         match = 1;
140     
141     odr_destroy(o1);
142     odr_destroy(o2);
143     if (!match)
144         return 0;
145
146     if (!syntax)
147         return 0;
148     // See if offset, OID match..
149     if (entry->m_offset == offset &&
150         entry->m_record->which == Z_NamePlusRecord_databaseRecord &&
151         !oid_oidcmp(entry->m_record->u.databaseRecord->direct_reference,
152                     syntax))
153         return 1;
154     return 0;
155 }
156
157 int Yaz_RecordCache::lookup (ODR o, Z_NamePlusRecordList **npr,
158                              int start, int num,
159                              Odr_oid *syntax,
160                              Z_RecordComposition *comp)
161 {
162     int i;
163     yaz_log(LOG_LOG, "cache lookup start=%d num=%d", start, num);
164
165     for (i = 0; i<num; i++)
166     {
167         Yaz_RecordCache_Entry *entry = m_entries;
168         for(; entry; entry = entry->m_next)
169             if (match(entry, syntax, start+i, comp))
170                 break;
171         if (!entry)
172             return 0;
173     }
174     *npr = (Z_NamePlusRecordList *) odr_malloc(o, sizeof(**npr));
175     (*npr)->num_records = num;
176     (*npr)->records = (Z_NamePlusRecord **)
177         odr_malloc(o, num * sizeof(Z_NamePlusRecord *));
178     for (i = 0; i<num; i++)
179     {
180         Yaz_RecordCache_Entry *entry = m_entries;
181         for(; entry; entry = entry->m_next)
182             if (match(entry, syntax, start+i, comp))
183                 break;
184         if (!entry)
185             return 0;
186         (*npr)->records[i] = entry->m_record;
187     }
188     return 1;
189 }