Use AM_LDFLAGS instead of LDFLAGS
[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.8 2004-01-24 21:32:31 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     m_max_size = 200000;
25 }
26
27 Yaz_RecordCache::~Yaz_RecordCache ()
28 {
29     nmem_destroy(m_mem);
30 }
31
32 void Yaz_RecordCache::set_max_size(int sz)
33 {
34     m_max_size = sz;
35 }
36
37 void Yaz_RecordCache::clear ()
38 {
39     nmem_destroy(m_mem);
40     m_mem = nmem_create();
41     m_entries = 0;
42     m_presentRequest = 0;
43     m_searchRequest = 0;
44 }
45
46 void Yaz_RecordCache::copy_searchRequest(Z_SearchRequest *sr)
47 {
48     ODR encode = odr_createmem(ODR_ENCODE);
49     ODR decode = odr_createmem(ODR_DECODE);
50
51     m_searchRequest = 0;
52     m_presentRequest = 0;
53     int v = z_SearchRequest (encode, &sr, 1, 0);
54     if (v)
55     {
56         int len;
57         char *buf = odr_getbuf(encode, &len, 0);
58         odr_setbuf(decode, buf, len, 0);
59         z_SearchRequest(decode, &m_searchRequest, 1, 0);
60         nmem_transfer(m_mem, decode->mem);
61     }
62     odr_destroy(encode);
63     odr_destroy(decode);
64 }
65
66 void Yaz_RecordCache::copy_presentRequest(Z_PresentRequest *pr)
67 {
68     ODR encode = odr_createmem(ODR_ENCODE);
69     ODR decode = odr_createmem(ODR_DECODE);
70     
71     m_searchRequest = 0;
72     m_presentRequest = 0;
73     int v = z_PresentRequest (encode, &pr, 1, 0);
74     if (v)
75     {
76         int len;
77         char *buf = odr_getbuf(encode, &len, 0);
78         odr_setbuf(decode, buf, len, 0);
79         z_PresentRequest(decode, &m_presentRequest, 1, 0);
80         nmem_transfer(m_mem, decode->mem);
81     }
82     odr_destroy(encode);
83     odr_destroy(decode);
84 }
85
86 void Yaz_RecordCache::add (ODR o, Z_NamePlusRecordList *npr, int start,
87                            int hits)
88 {
89     if (nmem_total(m_mem) > m_max_size)
90         return;
91     // Build appropriate compspec for this response
92     Z_RecordComposition *comp = 0;
93     if (hits == -1 && m_presentRequest)
94         comp = m_presentRequest->recordComposition;
95     else if (hits > 0 && m_searchRequest)
96     {
97         Z_ElementSetNames *esn;
98
99         if (hits <= *m_searchRequest->smallSetUpperBound)
100             esn = m_searchRequest->smallSetElementSetNames;
101         else
102             esn = m_searchRequest->mediumSetElementSetNames;
103         comp = (Z_RecordComposition *) nmem_malloc(m_mem, sizeof(*comp));
104         comp->which = Z_RecordComp_simple;
105         comp->u.simple = esn;
106     }
107
108     // Z_NamePlusRecordList *npr to be owned by m_mem..
109     NMEM tmp_mem = odr_extract_mem(o);
110     nmem_transfer(m_mem, tmp_mem);
111     nmem_destroy(tmp_mem);
112     
113     // Insert individual records in cache
114     int i;
115     for (i = 0; i<npr->num_records; i++)
116     {
117         Yaz_RecordCache_Entry *entry = (Yaz_RecordCache_Entry *)
118             nmem_malloc(m_mem, sizeof(*entry));
119         entry->m_record = (Z_NamePlusRecord *)
120             nmem_malloc(m_mem, sizeof(*entry->m_record));
121         entry->m_record->databaseName = npr->records[i]->databaseName;
122         entry->m_record->which = npr->records[i]->which;
123         entry->m_record->u.databaseRecord  = npr->records[i]->u.databaseRecord;
124         entry->m_comp = comp;
125         entry->m_offset = i + start;
126         entry->m_next = m_entries;
127         m_entries = entry;
128     }
129 }
130
131 int Yaz_RecordCache::match (Yaz_RecordCache_Entry *entry,
132                             Odr_oid *syntax, int offset,
133                             Z_RecordComposition *comp)
134 {
135     // See if our compspec match...
136     int match = 0;
137     ODR o1 = odr_createmem(ODR_ENCODE);
138     ODR o2 = odr_createmem(ODR_ENCODE);
139     
140     z_RecordComposition(o1, &comp, 1, 0);
141     z_RecordComposition(o2, &entry->m_comp, 1, 0);
142
143     int len1 = -1;
144     char *buf1 = odr_getbuf(o1, &len1, 0);
145     int len2 = -1;
146     char *buf2 = odr_getbuf(o2, &len2, 0);
147     
148     if (buf1 && buf2 && len1 && len1 == len2 && !memcmp(buf1, buf2, len1))
149         match = 1;
150     else if (!buf1 && !buf2 && !len1 && !len2)
151         match = 1;
152     
153     odr_destroy(o1);
154     odr_destroy(o2);
155     if (!match)
156         return 0;
157     if (!syntax)
158         return 0;
159     // See if offset, OID match..
160     if (entry->m_offset == offset &&
161         entry->m_record->which == Z_NamePlusRecord_databaseRecord &&
162         !oid_oidcmp(entry->m_record->u.databaseRecord->direct_reference,
163                     syntax))
164         return 1;
165 #if 0
166     char mstr1[100];
167     oid_to_dotstring(entry->m_record->u.databaseRecord->direct_reference, mstr1);
168     char mstr2[100];
169     oid_to_dotstring(syntax, mstr2);
170     yaz_log(LOG_LOG, "match fail 3 d=%s s=%s", mstr1, mstr2);
171 #endif
172
173     return 0;
174 }
175
176 int Yaz_RecordCache::lookup (ODR o, Z_NamePlusRecordList **npr,
177                              int start, int num,
178                              Odr_oid *syntax,
179                              Z_RecordComposition *comp)
180 {
181     int i;
182     yaz_log(LOG_DEBUG, "cache lookup start=%d num=%d", start, num);
183
184     for (i = 0; i<num; i++)
185     {
186         Yaz_RecordCache_Entry *entry = m_entries;
187         for(; entry; entry = entry->m_next)
188             if (match(entry, syntax, start+i, comp))
189                 break;
190         if (!entry)
191             return 0;
192     }
193     *npr = (Z_NamePlusRecordList *) odr_malloc(o, sizeof(**npr));
194     (*npr)->num_records = num;
195     (*npr)->records = (Z_NamePlusRecord **)
196         odr_malloc(o, num * sizeof(Z_NamePlusRecord *));
197     for (i = 0; i<num; i++)
198     {
199         Yaz_RecordCache_Entry *entry = m_entries;
200         for(; entry; entry = entry->m_next)
201             if (match(entry, syntax, start+i, comp))
202                 break;
203         if (!entry)
204             return 0;
205         (*npr)->records[i] = (Z_NamePlusRecord *)
206             odr_malloc(o, sizeof(Z_NamePlusRecord));
207         (*npr)->records[i]->databaseName = entry->m_record->databaseName;
208         (*npr)->records[i]->which = entry->m_record->which;
209         (*npr)->records[i]->u.databaseRecord =
210             entry->m_record->u.databaseRecord;
211     }
212     return 1;
213 }