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