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