New general match criteria implemented.
[idzebra-moved-to-github.git] / index / trav.c
1 /*
2  * Copyright (C) 1994-1995, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: trav.c,v $
7  * Revision 1.10  1995-11-21 15:01:16  adam
8  * New general match criteria implemented.
9  * New feature: document groups.
10  *
11  * Revision 1.9  1995/11/21  09:20:32  adam
12  * Yet more work on record match.
13  *
14  * Revision 1.8  1995/11/20  16:59:46  adam
15  * New update method: the 'old' keys are saved for each records.
16  *
17  * Revision 1.7  1995/11/20  11:56:28  adam
18  * Work on new traversal.
19  *
20  * Revision 1.6  1995/11/17  15:54:42  adam
21  * Started work on virtual directory structure.
22  *
23  * Revision 1.5  1995/10/17  18:02:09  adam
24  * New feature: databases. Implemented as prefix to words in dictionary.
25  *
26  * Revision 1.4  1995/09/28  09:19:46  adam
27  * xfree/xmalloc used everywhere.
28  * Extract/retrieve method seems to work for text records.
29  *
30  * Revision 1.3  1995/09/06  16:11:18  adam
31  * Option: only one word key per file.
32  *
33  * Revision 1.2  1995/09/04  12:33:43  adam
34  * Various cleanup. YAZ util used instead.
35  *
36  * Revision 1.1  1995/09/01  14:06:36  adam
37  * Split of work into more files.
38  *
39  */
40 #include <stdio.h>
41 #include <assert.h>
42 #include <unistd.h>
43 #include <dirent.h>
44 #include <sys/stat.h>
45 #include <sys/types.h>
46 #include <fcntl.h>
47 #include <ctype.h>
48
49 #include <alexutil.h>
50 #include "index.h"
51
52 static int repComp (const char *a, const char *b, size_t len)
53 {
54     if (!len)
55         return 0;
56     return memcmp (a, b, len);
57 }
58
59 static void repositoryExtractR (char *rep, struct recordGroup *rGroup)
60 {
61     struct dir_entry *e;
62     int i;
63     size_t rep_len = strlen (rep);
64
65     e = dir_open (rep);
66     if (!e)
67         return;
68     if (rep[rep_len-1] != '/')
69         rep[rep_len] = '/';
70     else
71         --rep_len;
72     for (i=0; e[i].name; i++)
73     {
74         strcpy (rep +rep_len+1, e[i].name);
75         switch (e[i].kind)
76         {
77         case dirs_file:
78             fileExtract (NULL, rep, rGroup, 0);
79             break;
80         case dirs_dir:
81             repositoryExtractR (rep, rGroup);
82             break;
83         }
84     }
85     dir_free (&e);
86
87 }
88
89 static void repositoryUpdateR (struct dirs_info *di, struct dirs_entry *dst,
90                                const char *base, char *src, 
91                                struct recordGroup *rGroup)
92 {
93     struct dir_entry *e_src;
94     int i_src = 0;
95     static char tmppath[256];
96     size_t src_len = strlen (src);
97
98     sprintf (tmppath, "%s%s", base, src);
99     e_src = dir_open (tmppath);
100
101 #if 1
102     if (!dst || repComp (dst->path, src, src_len))
103 #else
104     if (!dst || strcmp (dst->path, src))
105 #endif
106     {
107         if (!e_src)
108             return;
109         if (src_len && src[src_len-1] == '/')
110             --src_len;
111         else
112             src[src_len] = '/';
113         src[src_len+1] = '\0';
114         dirs_mkdir (di, src, 0);
115         dst = NULL;
116     }
117     else if (!e_src)
118     {
119         /* delete tree dst */
120         return;
121     }
122     else
123     {
124         if (src_len && src[src_len-1] == '/')
125             --src_len;
126         else
127             src[src_len] = '/';
128         src[src_len+1] = '\0';
129         dst = dirs_read (di); 
130     }
131     dir_sort (e_src);
132
133     while (1)
134     {
135         int sd;
136
137         if (dst && !repComp (dst->path, src, src_len+1))
138         {
139             if (e_src[i_src].name)
140             {
141                 logf (LOG_DEBUG, "dst=%s src=%s", dst->path + src_len+1, 
142                       e_src[i_src].name);
143                 sd = strcmp (dst->path + src_len+1, e_src[i_src].name);
144             }
145             else
146                 sd = -1;
147         }
148         else if (e_src[i_src].name)
149             sd = 1;
150         else
151             break;
152         logf (LOG_DEBUG, "trav sd=%d", sd);
153         if (sd == 0)
154         {
155             strcpy (src + src_len+1, e_src[i_src].name);
156             sprintf (tmppath, "%s%s", base, src);
157             
158             switch (e_src[i_src].kind)
159             {
160             case dirs_file:
161                 if (e_src[i_src].ctime > dst->ctime)
162                 {
163                     if (fileExtract (&dst->sysno, tmppath, rGroup, 0))
164                         dirs_add (di, src, dst->sysno, e_src[i_src].ctime);
165                 }
166                 dst = dirs_read (di);
167                 break;
168             case dirs_dir:
169                 repositoryUpdateR (di, dst, base, src, rGroup);
170                 dst = dirs_last (di);
171                 logf (LOG_DEBUG, "last is %s", dst ? dst->path : "null");
172                 break;
173             default:
174                 dst = dirs_read (di); 
175             }
176             i_src++;
177         }
178         else if (sd > 0)
179         {
180             SYSNO sysno = 0;
181             strcpy (src + src_len+1, e_src[i_src].name);
182             sprintf (tmppath, "%s%s", base, src);
183
184             switch (e_src[i_src].kind)
185             {
186             case dirs_file:
187                 if (fileExtract (&sysno, tmppath, rGroup, 0))
188                     dirs_add (di, src, sysno, e_src[i_src].ctime);            
189                 break;
190             case dirs_dir:
191                 repositoryUpdateR (di, dst, base, src, rGroup);
192                 if (dst)
193                     dst = dirs_last (di);
194                 break;
195             }
196             i_src++;
197         }
198         else  /* sd < 0 */
199         {
200             assert (0);
201         }
202     }
203     dir_free (&e_src);
204 }
205
206 void repositoryUpdate (struct recordGroup *rGroup)
207 {
208     struct dirs_info *di;
209     char src[256];
210     Dict dict;
211
212     dict = dict_open ("repdict", 40, 1);
213
214     assert (rGroup->path);
215     di = dirs_open (dict, rGroup->path);
216     strcpy (src, "");
217     repositoryUpdateR (di, dirs_read (di), rGroup->path, src, rGroup);
218     dirs_free (&di);
219
220     dict_close (dict);
221 }
222
223 void repositoryExtract (struct recordGroup *rGroup)
224 {
225     char src[256];
226
227     assert (rGroup->path);
228     strcpy (src, rGroup->path);
229     repositoryExtractR (src, rGroup);
230 }