Locking based on fcntl instead of flock.
[idzebra-moved-to-github.git] / index / main.c
1 /*
2  * Copyright (C) 1994-1995, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: main.c,v $
7  * Revision 1.29  1995-12-11 11:43:30  adam
8  * Locking based on fcntl instead of flock.
9  * Setting commitEnable removed. Command line option -n can be used to
10  * prevent commit if commit setting is defined in the configuration file.
11  *
12  * Revision 1.28  1995/12/08  16:22:56  adam
13  * Work on update while servers are running. Three lock files introduced.
14  * The servers reload their registers when necessary, but they don't
15  * reestablish result sets yet.
16  *
17  * Revision 1.27  1995/12/07  17:38:47  adam
18  * Work locking mechanisms for concurrent updates/commit.
19  *
20  * Revision 1.26  1995/12/06  12:41:23  adam
21  * New command 'stat' for the index program.
22  * Filenames can be read from stdin by specifying '-'.
23  * Bug fix/enhancement of the transformation from terms to regular
24  * expressons in the search engine.
25  *
26  * Revision 1.25  1995/12/01  16:24:39  adam
27  * Commit files use separate meta file area.
28  *
29  * Revision 1.24  1995/11/30  17:01:38  adam
30  * New setting commitCache: points to commit directories/files.
31  * New command commit: commits at the end of a zebraidx run.
32  *
33  * Revision 1.23  1995/11/30  08:34:31  adam
34  * Started work on commit facility.
35  * Changed a few malloc/free to xmalloc/xfree.
36  *
37  * Revision 1.22  1995/11/28  09:09:42  adam
38  * Zebra config renamed.
39  * Use setting 'recordId' to identify record now.
40  * Bug fix in recindex.c: rec_release_blocks was invokeded even
41  * though the blocks were already released.
42  * File traversal properly deletes records when needed.
43  *
44  * Revision 1.21  1995/11/27  14:27:39  adam
45  * Renamed 'update' command to 'dir'.
46  *
47  * Revision 1.20  1995/11/27  13:58:53  adam
48  * New option -t. storeStore data implemented in server.
49  *
50  * Revision 1.19  1995/11/25  10:24:06  adam
51  * More record fields - they are enumerated now.
52  * New options: flagStoreData flagStoreKey.
53  *
54  * Revision 1.18  1995/11/22  17:19:17  adam
55  * Record management uses the bfile system.
56  *
57  * Revision 1.17  1995/11/21  15:01:16  adam
58  * New general match criteria implemented.
59  * New feature: document groups.
60  *
61  * Revision 1.16  1995/11/20  11:56:27  adam
62  * Work on new traversal.
63  *
64  * Revision 1.15  1995/11/01  16:25:51  quinn
65  * *** empty log message ***
66  *
67  * Revision 1.14  1995/10/17  18:02:09  adam
68  * New feature: databases. Implemented as prefix to words in dictionary.
69  *
70  * Revision 1.13  1995/10/10  12:24:39  adam
71  * Temporary sort files are compressed.
72  *
73  * Revision 1.12  1995/10/04  16:57:20  adam
74  * Key input and merge sort in one pass.
75  *
76  * Revision 1.11  1995/09/29  14:01:45  adam
77  * Bug fixes.
78  *
79  * Revision 1.10  1995/09/28  14:22:57  adam
80  * Sort uses smaller temporary files.
81  *
82  * Revision 1.9  1995/09/14  07:48:24  adam
83  * Record control management.
84  *
85  * Revision 1.8  1995/09/06  16:11:18  adam
86  * Option: only one word key per file.
87  *
88  * Revision 1.7  1995/09/05  15:28:39  adam
89  * More work on search engine.
90  *
91  * Revision 1.6  1995/09/04  12:33:43  adam
92  * Various cleanup. YAZ util used instead.
93  *
94  * Revision 1.5  1995/09/04  09:10:39  adam
95  * More work on index add/del/update.
96  * Merge sort implemented.
97  * Initial work on z39 server.
98  *
99  * Revision 1.4  1995/09/01  14:06:36  adam
100  * Split of work into more files.
101  *
102  * Revision 1.3  1995/09/01  10:57:07  adam
103  * Minor changes.
104  *
105  * Revision 1.2  1995/09/01  10:30:24  adam
106  * More work on indexing. Not working yet.
107  *
108  * Revision 1.1  1995/08/31  14:50:24  adam
109  * New simple file index tool.
110  *
111  */
112 #include <stdio.h>
113 #include <assert.h>
114 #include <unistd.h>
115
116 #include <alexutil.h>
117 #include <data1.h>
118 #include "index.h"
119
120 char *prog;
121 size_t mem_max = 4*1024*1024;
122 extern char *data1_tabpath;
123
124 int main (int argc, char **argv)
125 {
126     int ret;
127     int cmd = 0;
128     char *arg;
129     char *configName = NULL;
130     int nsections;
131     int disableCommit = 0;
132
133     struct recordGroup rGroupDef;
134     
135     rGroupDef.groupName = NULL;
136     rGroupDef.databaseName = NULL;
137     rGroupDef.path = NULL;
138     rGroupDef.recordId = NULL;
139     rGroupDef.recordType = NULL;
140     rGroupDef.flagStoreData = -1;
141     rGroupDef.flagStoreKeys = -1;
142
143     prog = *argv;
144     if (argc < 2)
145     {
146         fprintf (stderr, "zebraidx [options] command <dir> ...\n"
147         "Commands:\n"
148         " update <dir>  Update index with files below <dir>.\n"
149         "               If <dir> is empty filenames are read from stdin.\n"
150         " delete <dir>  Delete index with files below <dir>.\n"
151         "Options:\n"
152         " -t <type>     Index files as <type> (grs or text).\n"
153         " -c <config>   Read configuration file <config>.\n"
154         " -g <group>    Index files according to group settings.\n"
155         " -d <database> Records belong to Z39.50 database <database>.\n"
156         " -m <mbytes>   Use <mbytes> before flushing keys to disk.\n"
157         " -n            Don't use commit system\n"
158         " -v <level>    Set logging to <level>.\n");
159         exit (1);
160     }
161     while ((ret = options ("t:c:g:d:m:v:n", argv, argc, &arg)) != -2)
162     {
163         if (ret == 0)
164         {
165             const char *rval;
166             if(cmd == 0) /* command */
167             {
168                 if (!common_resource)
169                 {
170                     common_resource = res_open (configName ?
171                                                 configName : FNAME_CONFIG);
172                     if (!common_resource)
173                     {
174                         logf (LOG_FATAL, "Cannot open resource `%s'",
175                               configName);
176                         exit (1);
177                     }
178                     data1_tabpath = res_get (common_resource, "profilePath");
179                 }
180                 if (!strcmp (arg, "update"))
181                     cmd = 'u';
182                 else if (!strcmp (arg, "del") || !strcmp(arg, "delete"))
183                     cmd = 'd';
184                 else if (!strcmp (arg, "commit"))
185                 {
186                     zebraIndexLock (1);
187                     rval = res_get (common_resource, "commit");
188                     if (rval && *rval)
189                         bf_cache (1);
190                     else
191                     {
192                         logf (LOG_FATAL, "Cannot perform commit");
193                         logf (LOG_FATAL, "No commit area defined "
194                               "in the configuration file");
195                         exit (1);
196                     }
197                     if (bf_commitExists ())
198                     {
199                         logf (LOG_LOG, "Commit start");
200                         zebraIndexLockMsg ("c");
201                         zebraIndexWait (1);
202                         logf (LOG_LOG, "Commit execute");
203                         bf_commitExec ();
204                         zebraIndexLockMsg ("d");
205                         zebraIndexWait (0);
206                         logf (LOG_LOG, "Commit clean");
207                         bf_commitClean ();
208                     }
209                     else
210                         logf (LOG_LOG, "Nothing to commit");
211                 }
212                 else if (!strcmp (arg, "stat") || !strcmp (arg, "status"))
213                 {
214                     zebraIndexLock (0);
215                     bf_cache (0);
216                     rec_prstat ();
217                 }
218                 else if (!strcmp (arg, "cstat") || !strcmp (arg, "cstatus"))
219                 {
220                     zebraIndexLock (1);
221                     rval = res_get (common_resource, "commit");
222                     if (rval && *rval)
223                     {
224                         bf_cache (1);
225                         zebraIndexLockMsg ("r");
226                     }
227                     rec_prstat ();
228                 }
229                 else
230                 {
231                     logf (LOG_FATAL, "Unknown command: %s", arg);
232                     exit (1);
233                 }
234             }
235             else
236             {
237                 struct recordGroup rGroup;
238
239                 zebraIndexLock (0);
240                 rval = res_get (common_resource, "commit");
241                 if (rval && *rval && !disableCommit)
242                 {
243                     bf_cache (1);
244                     zebraIndexLockMsg ("r");
245                 }
246                 else
247                 {
248                     bf_cache (0);
249                     zebraIndexLockMsg ("w");
250                 }
251                 zebraIndexWait (0);
252
253                 memcpy (&rGroup, &rGroupDef, sizeof(rGroup));
254                 key_open (mem_max);
255                 rGroup.path = arg;
256                 if (cmd == 'u')
257                 {
258                     logf (LOG_LOG, "Updating %s", rGroup.path);
259                     repositoryUpdate (&rGroup);
260                 }
261                 else if (cmd == 'd')
262                 {
263                     logf (LOG_LOG, "Deleting %s", rGroup.path);
264                     repositoryDelete (&rGroup);
265                 }
266                 cmd = 0;
267                 nsections = key_close ();
268                 if (nsections)
269                 {
270                     logf (LOG_LOG, "Merging with index");
271                     key_input (FNAME_WORD_DICT, FNAME_WORD_ISAM, nsections,
272                                60);
273                 }
274             }
275         }
276         else if (ret == 'v')
277         {
278             log_init (log_mask_str(arg), prog, NULL);
279         }
280         else if (ret == 'm')
281         {
282             mem_max = 1024*1024*atoi(arg);
283         }
284         else if (ret == 'd')
285         {
286             rGroupDef.databaseName = arg;
287         }
288         else if (ret == 'g')
289         {
290             rGroupDef.groupName = arg;
291         }
292         else if (ret == 'c')
293             configName = arg;
294         else if (ret == 't')
295             rGroupDef.recordType = arg;
296         else if (ret == 'n')
297             disableCommit = 1;
298         else
299         {
300             logf (LOG_FATAL, "Unknown option '-%s'", arg);
301             exit (1);
302         }
303     }
304     zebraIndexUnlock ();
305     exit (0);
306 }
307