Happy new year
[yaz-moved-to-github.git] / client / admin.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2009 Index Data
3  * See the file LICENSE for details.
4  */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <time.h>
9 #include <assert.h>
10
11 #if HAVE_DIRENT_H
12 #include <dirent.h>
13 #endif
14 #if HAVE_FNMATCH_H
15 #include <fnmatch.h>
16 #endif
17 #if HAVE_SYS_STAT_H
18 #include <sys/stat.h>
19 #endif
20
21 #include <yaz/yaz-util.h>
22
23 #include <yaz/tcpip.h>
24
25 #include <yaz/proto.h>
26 #include <yaz/marcdisp.h>
27 #include <yaz/diagbib1.h>
28 #include <yaz/oid_db.h>
29 #include <yaz/pquery.h>
30
31 #include "admin.h"
32
33 /* Helper functions to get to various statics in the client */
34 ODR getODROutputStream(void);
35
36 extern char *databaseNames[];
37 extern int num_databaseNames;
38
39 int sendAdminES(int type, char* param1)
40 {
41     ODR out = getODROutputStream();
42     char *dbname = odr_strdup (out, databaseNames[0]);
43     
44     /* Type: 1=reindex, 2=truncate, 3=delete, 4=create, 5=import, 6=refresh, 7=commit */
45     Z_APDU *apdu = zget_APDU(out, Z_APDU_extendedServicesRequest );
46     Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest;
47     Z_External *r;
48     Odr_oid *oid;
49     Z_ESAdminOriginPartToKeep  *toKeep;
50     Z_ESAdminOriginPartNotToKeep  *notToKeep;
51     printf ("Admin request\n");
52     fflush(stdout);
53
54     oid = odr_oiddup(out, yaz_oid_extserv_admin);
55
56     req->packageType = oid;
57     req->packageName = "1.Extendedserveq";
58
59     /* Allocate the external */
60     r = req->taskSpecificParameters = (Z_External *)
61         odr_malloc (out, sizeof(*r));
62     r->direct_reference = odr_oiddup(out,oid);
63     r->indirect_reference = 0;
64     r->descriptor = 0;
65     r->which = Z_External_ESAdmin;
66     r->u.adminService = (Z_Admin *)
67         odr_malloc(out, sizeof(*r->u.adminService));
68     r->u.adminService->which = Z_Admin_esRequest;
69     r->u.adminService->u.esRequest = (Z_AdminEsRequest *)
70         odr_malloc(out, sizeof(*r->u.adminService->u.esRequest));
71     
72     toKeep = r->u.adminService->u.esRequest->toKeep =
73         (Z_ESAdminOriginPartToKeep *) 
74         odr_malloc(out, sizeof(*r->u.adminService->u.esRequest->toKeep));
75     
76     toKeep->which=type;
77     toKeep->databaseName = dbname;
78     switch ( type )
79     {
80     case Z_ESAdminOriginPartToKeep_reIndex:
81         toKeep->u.reIndex=odr_nullval();
82         break;
83         
84     case Z_ESAdminOriginPartToKeep_truncate:
85         toKeep->u.truncate=odr_nullval();
86         break;
87     case Z_ESAdminOriginPartToKeep_drop:
88         toKeep->u.drop=odr_nullval();
89         break;
90     case Z_ESAdminOriginPartToKeep_create:
91         toKeep->u.create=odr_nullval();
92         break;
93     case Z_ESAdminOriginPartToKeep_import:
94         toKeep->u.import = (Z_ImportParameters*)
95             odr_malloc(out, sizeof(*toKeep->u.import));
96         toKeep->u.import->recordType=param1;
97         /* Need to add additional setup of records here */
98         break;
99     case Z_ESAdminOriginPartToKeep_refresh:
100         toKeep->u.refresh=odr_nullval();
101         break;
102     case Z_ESAdminOriginPartToKeep_commit:
103         toKeep->u.commit=odr_nullval();
104         break;
105     case Z_ESAdminOriginPartToKeep_shutdown:
106         toKeep->u.commit=odr_nullval();
107         break;
108     case Z_ESAdminOriginPartToKeep_start:
109         toKeep->u.commit=odr_nullval();
110         break;
111     default:
112         /* Unknown admin service */
113         break;
114     }
115     
116     notToKeep = r->u.adminService->u.esRequest->notToKeep =
117         (Z_ESAdminOriginPartNotToKeep *)
118         odr_malloc(out, sizeof(*r->u.adminService->u.esRequest->notToKeep));
119     notToKeep->which=Z_ESAdminOriginPartNotToKeep_recordsWillFollow;
120     notToKeep->u.recordsWillFollow=odr_nullval();
121     
122     send_apdu(apdu);
123     
124     return 0;
125 }
126
127 /* cmd_adm_reindex
128    Ask the specified database to fully reindex itself */
129 int cmd_adm_reindex(const char *arg)
130 {
131     sendAdminES(Z_ESAdminOriginPartToKeep_reIndex, NULL);
132     return 2;
133 }
134
135 /* cmd_adm_truncate
136    Truncate the specified database, removing all records and index entries, but leaving 
137    the database & it's explain information intact ready for new records */
138 int cmd_adm_truncate(const char *arg)
139 {
140     if ( arg )
141     {
142         sendAdminES(Z_ESAdminOriginPartToKeep_truncate, NULL);
143         return 2;
144     }
145     return 0;
146 }
147
148 /* cmd_adm_create
149    Create a new database */
150 int cmd_adm_create(const char *arg)
151 {
152     if ( arg )
153     {
154         sendAdminES(Z_ESAdminOriginPartToKeep_create, NULL);
155         return 2;
156     }
157     return 0;
158 }
159
160 /* cmd_adm_drop
161    Drop (Delete) a database */
162 int cmd_adm_drop(const char *arg)
163 {
164     if ( arg )
165     {
166         sendAdminES(Z_ESAdminOriginPartToKeep_drop, NULL);
167         return 2;
168     }
169     return 0;
170 }
171
172 /* cmd_adm_import <dbname> <rectype> <sourcefile>
173    Import the specified updated into the database
174    N.B. That in this case, the import may contain instructions to delete records as well as new or updates
175    to existing records */
176
177 #if HAVE_FNMATCH_H
178 int cmd_adm_import(const char *arg)
179 {
180     char type_str[20], dir_str[1024], pattern_str[1024];
181     char *cp;
182     char *sep = "/";
183     DIR *dir;
184     struct dirent *ent;
185     int chunk = 10;
186     Z_APDU *apdu = 0;
187     Z_Segment *segment = 0;
188     ODR out = getODROutputStream();
189
190     if (arg && sscanf (arg, "%19s %1023s %1023s", type_str,
191                        dir_str, pattern_str) != 3)
192         return 0;
193     if (num_databaseNames != 1)
194         return 0;
195     dir = opendir(dir_str);
196     if (!dir)
197         return 0;
198     
199     sendAdminES(Z_ESAdminOriginPartToKeep_import, type_str);
200     
201     printf ("sent es request\n");
202     if ((cp=strrchr(dir_str, '/')) && cp[1] == 0)
203         sep="";
204         
205     while ((ent = readdir(dir)))
206     {
207         if (fnmatch (pattern_str, ent->d_name, 0) == 0)
208         {
209             char fname[1024];
210             struct stat status;
211             FILE *inf;
212                 
213             sprintf (fname, "%s%s%s", dir_str, sep, ent->d_name);
214             stat (fname, &status);
215
216             if (S_ISREG(status.st_mode) && (inf = fopen(fname, "r")))
217             {
218                 Z_NamePlusRecord *rec;
219                 Odr_oct *oct = (Odr_oct *) odr_malloc (out, sizeof(*oct));
220
221                 if (!apdu)
222                 {
223                     apdu = zget_APDU(out, Z_APDU_segmentRequest);
224                     segment = apdu->u.segmentRequest;
225                     segment->segmentRecords = (Z_NamePlusRecord **)
226                         odr_malloc (out, chunk * sizeof(*segment->segmentRecords));
227                 }
228                 rec = (Z_NamePlusRecord *) odr_malloc (out, sizeof(*rec));
229                 rec->databaseName = 0;
230                 rec->which = Z_NamePlusRecord_intermediateFragment;
231                 rec->u.intermediateFragment = (Z_FragmentSyntax *)
232                     odr_malloc (out, sizeof(*rec->u.intermediateFragment));
233                 rec->u.intermediateFragment->which =
234                     Z_FragmentSyntax_notExternallyTagged;
235                 rec->u.intermediateFragment->u.notExternallyTagged = oct;
236                 
237                 oct->len = oct->size = status.st_size;
238                 oct->buf = (unsigned char *) odr_malloc (out, oct->size);
239                 if (fread(oct->buf, 1, oct->size, inf) != oct->size)
240                 {
241                     printf("Incomplete read of file %s\n", fname);
242                 }
243                 if (fclose(inf))
244                 {
245                     printf("Close failed for file %s\n", fname);
246                 }
247                 
248                 segment->segmentRecords[segment->num_segmentRecords++] = rec;
249
250                 if (segment->num_segmentRecords == chunk)
251                 {
252                     send_apdu (apdu);
253                     apdu = 0;
254                 }
255             }   
256         }
257     }
258     if (apdu)
259         send_apdu(apdu);
260     apdu = zget_APDU(out, Z_APDU_segmentRequest);
261     send_apdu (apdu);
262     closedir(dir);
263     return 2;
264 }
265 #else
266 int cmd_adm_import(const char *arg)
267 {
268     printf ("not available on WIN32\n");
269     return 0;
270 }
271 #endif
272
273
274 /* "Freshen" the specified database, by checking metadata records against the sources from which they were 
275    generated, and creating a new record if the source has been touched since the last extraction */
276 int cmd_adm_refresh(const char *arg)
277 {
278     if ( arg )
279     {
280         sendAdminES(Z_ESAdminOriginPartToKeep_refresh, NULL);
281         return 2;
282     }
283     return 0;
284 }
285
286 /* cmd_adm_commit 
287    Make imported records a permenant & visible to the live system */
288 int cmd_adm_commit(const char *arg)
289 {
290     sendAdminES(Z_ESAdminOriginPartToKeep_commit, NULL);
291     return 2;
292 }
293
294 int cmd_adm_shutdown(const char *arg)
295 {
296     sendAdminES(Z_ESAdminOriginPartToKeep_shutdown, NULL);
297     return 2;
298 }
299
300 int cmd_adm_startup(const char *arg)
301 {
302     sendAdminES(Z_ESAdminOriginPartToKeep_start, NULL);
303     return 2;
304 }
305 /*
306  * Local variables:
307  * c-basic-offset: 4
308  * indent-tabs-mode: nil
309  * End:
310  * vim: shiftwidth=4 tabstop=8 expandtab
311  */
312