New result set model and modular ranking system. Moved towards
[idzebra-moved-to-github.git] / index / kcompare.c
1 /*
2  * Copyright (C) 1994-1998, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: kcompare.c,v $
7  * Revision 1.23  1998-03-05 08:45:12  adam
8  * New result set model and modular ranking system. Moved towards
9  * descent server API. System information stored as "SGML" records.
10  *
11  * Revision 1.22  1997/09/22 12:39:06  adam
12  * Added get_pos method for the ranked result sets.
13  *
14  * Revision 1.21  1997/09/17 12:19:13  adam
15  * Zebra version corresponds to YAZ version 1.4.
16  * Changed Zebra server so that it doesn't depend on global common_resource.
17  *
18  * Revision 1.20  1996/12/23 15:30:44  adam
19  * Work on truncation.
20  * Bug fix: result sets weren't deleted after server shut down.
21  *
22  * Revision 1.19  1996/12/11 12:08:00  adam
23  * Added better compression.
24  *
25  * Revision 1.18  1996/10/29 14:09:44  adam
26  * Use of cisam system - enabled if setting isamc is 1.
27  *
28  * Revision 1.17  1996/06/04 10:18:58  adam
29  * Minor changes - removed include of ctype.h.
30  *
31  * Revision 1.16  1996/05/13  14:23:05  adam
32  * Work on compaction of set/use bytes in dictionary.
33  *
34  * Revision 1.15  1995/11/20  16:59:46  adam
35  * New update method: the 'old' keys are saved for each records.
36  *
37  * Revision 1.14  1995/10/30  15:08:08  adam
38  * Bug fixes.
39  *
40  * Revision 1.13  1995/10/27  14:00:11  adam
41  * Implemented detection of database availability.
42  *
43  * Revision 1.12  1995/10/17  18:02:08  adam
44  * New feature: databases. Implemented as prefix to words in dictionary.
45  *
46  * Revision 1.11  1995/10/06  16:33:37  adam
47  * Use attribute mappings.
48  *
49  * Revision 1.10  1995/09/29  14:01:41  adam
50  * Bug fixes.
51  *
52  * Revision 1.9  1995/09/28  12:10:32  adam
53  * Bug fixes. Field prefix used in queries.
54  *
55  * Revision 1.8  1995/09/28  09:19:42  adam
56  * xfree/xmalloc used everywhere.
57  * Extract/retrieve method seems to work for text records.
58  *
59  * Revision 1.7  1995/09/27  12:22:28  adam
60  * More work on extract in record control.
61  * Field name is not in isam keys but in prefix in dictionary words.
62  *
63  * Revision 1.6  1995/09/14  07:48:23  adam
64  * Record control management.
65  *
66  * Revision 1.5  1995/09/11  13:09:34  adam
67  * More work on relevance feedback.
68  *
69  * Revision 1.4  1995/09/08  14:52:27  adam
70  * Minor changes. Dictionary is lower case now.
71  *
72  * Revision 1.3  1995/09/07  13:58:36  adam
73  * New parameter: result-set file descriptor (RSFD) to support multiple
74  * positions within the same result-set.
75  * Boolean operators: and, or, not implemented.
76  * Result-set references.
77  *
78  * Revision 1.2  1995/09/06  16:11:17  adam
79  * Option: only one word key per file.
80  *
81  * Revision 1.1  1995/09/04  09:10:36  adam
82  * More work on index add/del/update.
83  * Merge sort implemented.
84  * Initial work on z39 server.
85  *
86  */
87
88 #include <stdlib.h>
89 #include <string.h>
90 #include <stdio.h>
91 #include <assert.h>
92
93 #include "index.h"
94
95 void key_logdump (int logmask, const void *p)
96 {
97     struct it_key key;
98
99     memcpy (&key, p, sizeof(key));
100     logf (logmask, "%7d s=%-4d", key.sysno, key.seqno);
101 }
102
103 int key_compare_it (const void *p1, const void *p2)
104 {
105     if (((struct it_key *) p1)->sysno != ((struct it_key *) p2)->sysno)
106     {
107         if (((struct it_key *) p1)->sysno > ((struct it_key *) p2)->sysno)
108             return 2;
109         else
110             return -2;
111     }
112     if (((struct it_key *) p1)->seqno != ((struct it_key *) p2)->seqno)
113     {
114         if (((struct it_key *) p1)->seqno > ((struct it_key *) p2)->seqno)
115             return 1;
116         else
117             return -1;
118     }
119     return 0;
120 }
121
122 int key_compare (const void *p1, const void *p2)
123 {
124     struct it_key i1, i2;
125     memcpy (&i1, p1, sizeof(i1));
126     memcpy (&i2, p2, sizeof(i2));
127     if (i1.sysno != i2.sysno)
128     {
129         if (i1.sysno > i2.sysno)
130             return 2;
131         else
132             return -2;
133     }
134     if (i1.seqno != i2.seqno)
135     {
136         if (i1.seqno > i2.seqno)
137             return 1;
138         else
139             return -1;
140     }
141     return 0;
142 }
143
144 int key_qsort_compare (const void *p1, const void *p2)
145 {
146     int r;
147     size_t l;
148     char *cp1 = *(char **) p1;
149     char *cp2 = *(char **) p2;
150  
151     if ((r = strcmp (cp1, cp2)))
152         return r;
153     l = strlen(cp1)+1;
154     if ((r = key_compare (cp1+l+1, cp2+l+1)))
155         return r;
156     return cp1[l] - cp2[l];
157 }
158
159 int key_get_pos (const void *p)
160 {
161     struct it_key key;
162     memcpy (&key, p, sizeof(key));
163     return key.seqno;
164 }
165
166 struct iscz1_code_info {
167     struct it_key key;
168 };
169
170 static void *iscz1_code_start (int mode)
171 {
172     struct iscz1_code_info *p = xmalloc (sizeof(*p));
173     p->key.sysno = 0;
174     p->key.seqno = 0;
175     return p;
176 }
177
178 static void iscz1_code_stop (int mode, void *p)
179 {
180     xfree (p);
181 }
182
183 void iscz1_encode_int (unsigned d, char **dst)
184 {
185     unsigned char *bp = (unsigned char*) *dst;
186
187     if (d <= 63)
188         *bp++ = d;
189     else if (d <= 16383)
190     {
191         *bp++ = 64 + (d>>8);
192        *bp++ = d & 255;
193     }
194     else if (d <= 4194303)
195     {
196         *bp++ = 128 + (d>>16);
197         *bp++ = (d>>8) & 255;
198         *bp++ = d & 255;
199     }
200     else
201     {
202         *bp++ = 192 + (d>>24);
203         *bp++ = (d>>16) & 255;
204         *bp++ = (d>>8) & 255;
205         *bp++ = d & 255;
206     }
207     *dst = (char *) bp;
208 }
209
210 int iscz1_decode_int (unsigned char **src)
211 {
212     unsigned c = *(*src)++;
213     switch (c & 192)
214     {
215     case 0:
216         return c;
217     case 64:
218         return ((c & 63) << 8) + *(*src)++;
219     case 128:
220         c = ((c & 63) << 8) + *(*src)++;
221         c = (c << 8) + *(*src)++;
222         return c;
223     }
224     c = ((c & 63) << 8) + *(*src)++;
225     c = (c << 8) + *(*src)++;
226     c = (c << 8) + *(*src)++;
227     return c;
228 }
229
230 static void iscz1_code_item (int mode, void *vp, char **dst, char **src)
231 {
232     struct iscz1_code_info *p = vp;
233     struct it_key tkey;
234     int d;
235
236     if (mode == ISAMC_ENCODE)
237     {
238         memcpy (&tkey, *src, sizeof(struct it_key));
239         d = tkey.sysno - p->key.sysno;
240         if (d)
241         {
242             iscz1_encode_int (2*tkey.seqno + 1, dst);
243             iscz1_encode_int (d, dst);
244             p->key.sysno += d;
245             p->key.seqno = tkey.seqno;
246         }
247         else
248         {
249             iscz1_encode_int (2*(tkey.seqno - p->key.seqno), dst);
250             p->key.seqno = tkey.seqno;
251         }
252         (*src) += sizeof(struct it_key);
253     }
254     else
255     {
256         d = iscz1_decode_int ((unsigned char **) src);
257         if (d & 1)
258         {
259             p->key.seqno = d>>1;
260             p->key.sysno += iscz1_decode_int ((unsigned char **) src);
261         }
262         else
263             p->key.seqno += d>>1;
264         memcpy (*dst, &p->key, sizeof(struct it_key));
265         (*dst) += sizeof(struct it_key);
266     }
267 }
268
269 ISAMC_M key_isamc_m (Res res)
270 {
271     static ISAMC_M me = NULL;
272
273     if (me)
274         return me;
275
276     me = isc_getmethod ();
277
278     me->compare_item = key_compare;
279
280     me->code_start = iscz1_code_start;
281     me->code_item = iscz1_code_item;
282     me->code_stop = iscz1_code_stop;
283
284     me->debug = atoi(res_get_def (res, "isamcDebug", "0"));
285
286     return me;
287 }
288