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