More gils CCL field mappings.
[yaz-moved-to-github.git] / client / admin.c
1 /*
2  * $Log: admin.c,v $
3  * Revision 1.8  2000-04-17 14:21:38  adam
4  * WIN32 update.
5  *
6  * Revision 1.7  2000/04/05 07:39:54  adam
7  * Added shared library support (libtool).
8  *
9  * Revision 1.6  2000/03/20 19:06:25  adam
10  * Added Segment request for fronend server. Work on admin for client.
11  *
12  * Revision 1.5  2000/03/17 12:47:02  adam
13  * Minor changes to admin client.
14  *
15  * Revision 1.4  2000/03/16 13:55:49  ian
16  * Added commands for sending shutdown and startup admin requests via the admin ES.
17  *
18  * Revision 1.3  2000/03/14 15:23:17  ian
19  * Removed unwanted ifdef and include of zes-admin.h
20  *
21  * Revision 1.2  2000/03/14 14:06:04  ian
22  * Minor change to order of debugging output for send_apdu,
23  * fixed encoding of admin request.
24  *
25  * Revision 1.1  2000/03/14 09:27:07  ian
26  * Added code to enable sending of admin extended service requests
27  *
28  *
29  */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <time.h>
34 #include <assert.h>
35
36 #ifdef WIN32
37
38 #else
39 #include <dirent.h>
40 #include <fnmatch.h>
41 #include <sys/stat.h>
42 #endif
43
44 #include <yaz/yaz-util.h>
45
46 #include <yaz/tcpip.h>
47 #ifdef USE_XTIMOSI
48 #include <yaz/xmosi.h>
49 #endif
50
51 #include <yaz/proto.h>
52 #include <yaz/marcdisp.h>
53 #include <yaz/diagbib1.h>
54
55 #include <yaz/pquery.h>
56
57 #ifdef ASN_COMPILED
58
59 /* Helper functions to get to various statics in the client */
60 ODR getODROutputStream();
61 void send_apdu(Z_APDU *a);
62
63 extern char *databaseNames[];
64 extern int num_databaseNames;
65
66 int sendAdminES(int type, char* param1)
67 {
68     ODR out = getODROutputStream();
69     char *dbname = odr_strdup (out, databaseNames[0]);
70
71     /* Type: 1=reindex, 2=truncate, 3=delete, 4=create, 5=import, 6=refresh, 7=commit */
72     Z_APDU *apdu = zget_APDU(out, Z_APDU_extendedServicesRequest );
73     Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest;
74     Z_External *r;
75     int oid[OID_SIZE];
76     Z_ESAdminOriginPartToKeep  *toKeep;
77     Z_ESAdminOriginPartNotToKeep  *notToKeep;
78     oident update_oid;
79     printf ("Admin request\n");
80     fflush(stdout);
81
82     /* Set up the OID for the external */
83     update_oid.proto = PROTO_Z3950;
84     update_oid.oclass = CLASS_EXTSERV;
85     update_oid.value = VAL_ADMINSERVICE;
86
87     oid_ent_to_oid (&update_oid, oid);
88     req->packageType = odr_oiddup(out,oid);
89     req->packageName = "1.Extendedserveq";
90
91     /* Allocate the external */
92     r = req->taskSpecificParameters = (Z_External *) odr_malloc (out, sizeof(*r));
93     r->direct_reference = odr_oiddup(out,oid);
94     r->indirect_reference = 0;
95     r->descriptor = 0;
96     r->which = Z_External_ESAdmin;
97     r->u.adminService = (Z_Admin *) odr_malloc(out, sizeof(*r->u.adminService));
98     r->u.adminService->which = Z_Admin_esRequest;
99     r->u.adminService->u.esRequest = (Z_AdminEsRequest *) odr_malloc(out, sizeof(*r->u.adminService->u.esRequest));
100
101     toKeep = r->u.adminService->u.esRequest->toKeep = (Z_ESAdminOriginPartToKeep *) 
102                      odr_malloc(out, sizeof(*r->u.adminService->u.esRequest->toKeep));
103
104     toKeep->which=type;
105     toKeep->databaseName = dbname;
106     switch ( type )
107     {
108     case Z_ESAdminOriginPartToKeep_reIndex:
109         toKeep->u.reIndex=odr_nullval();
110         break;
111         
112     case Z_ESAdminOriginPartToKeep_truncate:
113         toKeep->u.truncate=odr_nullval();
114         break;
115     case Z_ESAdminOriginPartToKeep_drop:
116         toKeep->u.drop=odr_nullval();
117         break;
118     case Z_ESAdminOriginPartToKeep_create:
119         toKeep->u.create=odr_nullval();
120         break;
121     case Z_ESAdminOriginPartToKeep_import:
122         toKeep->u.import = (Z_ImportParameters*)odr_malloc(out, sizeof(*toKeep->u.import));
123         toKeep->u.import->recordType=param1;
124         /* Need to add additional setup of records here */
125         break;
126     case Z_ESAdminOriginPartToKeep_refresh:
127         toKeep->u.refresh=odr_nullval();
128         break;
129     case Z_ESAdminOriginPartToKeep_commit:
130         toKeep->u.commit=odr_nullval();
131         break;
132     case Z_ESAdminOriginPartToKeep_shutdown:
133         toKeep->u.commit=odr_nullval();
134         break;
135     case Z_ESAdminOriginPartToKeep_start:
136         toKeep->u.commit=odr_nullval();
137         break;
138     default:
139         /* Unknown admin service */
140         break;
141     }
142
143     notToKeep = r->u.adminService->u.esRequest->notToKeep =
144         (Z_ESAdminOriginPartNotToKeep *)
145         odr_malloc(out, sizeof(*r->u.adminService->u.esRequest->notToKeep));
146     notToKeep->which=Z_ESAdminOriginPartNotToKeep_recordsWillFollow;
147     notToKeep->u.recordsWillFollow=odr_nullval();
148     
149     send_apdu(apdu);
150     
151     return 0;
152 }
153
154 /* cmd_adm_reindex
155    Ask the specified database to fully reindex itself */
156 int cmd_adm_reindex(char* arg)
157 {
158     sendAdminES(Z_ESAdminOriginPartToKeep_reIndex, NULL);
159     return 2;
160 }
161
162 /* cmd_adm_truncate
163    Truncate the specified database, removing all records and index entries, but leaving 
164    the database & it's explain information intact ready for new records */
165 int cmd_adm_truncate(char* arg)
166 {
167     if ( arg )
168     {
169         sendAdminES(Z_ESAdminOriginPartToKeep_truncate, NULL);
170         return 2;
171     }
172     return 0;
173 }
174
175 /* cmd_adm_create
176    Create a new database */
177 int cmd_adm_create(char* arg)
178 {
179     if ( arg )
180     {
181         sendAdminES(Z_ESAdminOriginPartToKeep_create, NULL);
182         return 2;
183     }
184     return 0;
185 }
186
187 /* cmd_adm_drop
188    Drop (Delete) a database */
189 int cmd_adm_drop(char* arg)
190 {
191     if ( arg )
192     {
193         sendAdminES(Z_ESAdminOriginPartToKeep_drop, NULL);
194         return 2;
195     }
196     return 0;
197 }
198
199 /* cmd_adm_import <dbname> <rectype> <sourcefile>
200    Import the specified updated into the database
201    N.B. That in this case, the import may contain instructions to delete records as well as new or updates
202    to existing records */
203
204 #ifdef WIN32
205 int cmd_adm_import(char *arg)
206 {
207     printf ("not available on WIN32\n");
208     return 0;
209 }
210
211 #else
212
213 int cmd_adm_import(char *arg)
214 {
215     char type_str[20], dir_str[1024], pattern_str[1024];
216     char *cp;
217     char *sep = "/";
218     DIR *dir;
219     struct dirent *ent;
220     int chunk = 10;
221     Z_APDU *apdu = 0;
222     ODR out = getODROutputStream();
223
224     if (arg && sscanf (arg, "%19s %1023s %1023s", type_str,
225                        dir_str, pattern_str) != 3)
226         return 0;
227     if (num_databaseNames != 1)
228         return 0;
229     dir = opendir(dir_str);
230     if (!dir)
231         return 0;
232     
233     sendAdminES(Z_ESAdminOriginPartToKeep_import, type_str);
234
235     printf ("sent es request\n");
236     if ((cp=strrchr(dir_str, '/')) && cp[1] == 0)
237         sep="";
238         
239     while ((ent = readdir(dir)))
240     {
241         if (fnmatch (pattern_str, ent->d_name, 0) == 0)
242         {
243             char fname[1024];
244             struct stat status;
245             FILE *inf;
246                 
247             sprintf (fname, "%s%s%s", dir_str, sep, ent->d_name);
248             stat (fname, &status);
249
250             if (S_ISREG(status.st_mode) && (inf = fopen(fname, "r")))
251             {
252                 Z_Segment *segment;
253                 Z_NamePlusRecord *rec;
254                 Odr_oct *oct = odr_malloc (out, sizeof(*oct));
255
256                 if (!apdu)
257                 {
258                     apdu = zget_APDU(out, Z_APDU_segmentRequest);
259                     segment = apdu->u.segmentRequest;
260                     segment->segmentRecords = (Z_NamePlusRecord **)
261                         odr_malloc (out, chunk * sizeof(*segment->segmentRecords));
262                 }
263                 rec = (Z_NamePlusRecord *) odr_malloc (out, sizeof(*rec));
264                 rec->databaseName = 0;
265                 rec->which = Z_NamePlusRecord_intermediateFragment;
266                 rec->u.intermediateFragment = (Z_FragmentSyntax *)
267                     odr_malloc (out, sizeof(*rec->u.intermediateFragment));
268                 rec->u.intermediateFragment->which =
269                     Z_FragmentSyntax_notExternallyTagged;
270                 rec->u.intermediateFragment->u.notExternallyTagged = oct;
271                 
272                 oct->len = oct->size = status.st_size;
273                 oct->buf = odr_malloc (out, oct->size);
274                 fread (oct->buf, 1, oct->size, inf);
275                 fclose (inf);
276                 
277                 segment->segmentRecords[segment->num_segmentRecords++] = rec;
278
279                 if (segment->num_segmentRecords == chunk)
280                 {
281                     send_apdu (apdu);
282                     apdu = 0;
283                 }
284             }   
285         }
286     }
287     if (apdu)
288         send_apdu(apdu);
289     apdu = zget_APDU(out, Z_APDU_segmentRequest);
290     send_apdu (apdu);
291     closedir(dir);
292     return 2;
293 }
294 #endif
295
296 int cmd_adm_import2(char* arg)
297 {
298    /* Buffer for reading chunks of data from import file */
299     char chunk_buffer[8192];
300     
301     if ( arg )
302     {
303         char rectype_buff[32];
304         char filename_buff[32];
305         FILE* pImportFile = NULL;
306
307         if (sscanf (arg, "%s %s", rectype_buff, filename_buff) != 3)
308         {
309             printf("Must specify database-name, record-type and filename for import\n");
310             return 0;
311         }
312
313         /* Attempt to open the file */
314
315         pImportFile = fopen(filename_buff,"r");
316
317         /* This chunk of code should move into client.c sometime soon for sending files via the update es */
318         /* This function will then refer to the standard client.c one for uploading a file using es update */
319         if ( pImportFile )
320         {
321             int iTotalWritten = 0;
322
323             /* We opened the import file without problems... So no we send the es request, ready to 
324                start sending fragments of the import file as segment messages */
325             sendAdminES(Z_ESAdminOriginPartToKeep_import, rectype_buff);
326
327             while ( ! feof(pImportFile ) )
328             {
329                 /* Read buffer_size bytes from the file */
330                 size_t num_items = fread((void*)chunk_buffer, 1, sizeof(chunk_buffer),  pImportFile);
331
332                 /* Write num_bytes of data to */
333
334                 if ( feof(pImportFile ) )
335                 {
336                     /* This is the last chunk... Write it as the last fragment */
337                     printf("Last segment of %d bytes\n", num_items);
338                 }
339                 else if ( iTotalWritten == 0 )
340                 {
341                     printf("First segment of %d bytes\n",num_items);
342                 }
343                 else
344                 {
345                     printf("Writing %d bytes\n", num_items);
346                 }
347
348                 iTotalWritten += num_items;
349             }
350         }
351         return 2;
352     }
353     return 0;
354 }
355
356 /* "Freshen" the specified database, by checking metadata records against the sources from which they were 
357    generated, and creating a new record if the source has been touched since the last extraction */
358 int cmd_adm_refresh(char* arg)
359 {
360     if ( arg )
361     {
362         sendAdminES(Z_ESAdminOriginPartToKeep_refresh, NULL);
363         return 2;
364     }
365     return 0;
366 }
367
368 /* cmd_adm_commit 
369    Make imported records a permenant & visible to the live system */
370 int cmd_adm_commit(char* arg)
371 {
372     sendAdminES(Z_ESAdminOriginPartToKeep_commit, NULL);
373     return 2;
374 }
375
376 int cmd_adm_shutdown(char* arg)
377 {
378     sendAdminES(Z_ESAdminOriginPartToKeep_shutdown, NULL);
379     return 2;
380 }
381
382 int cmd_adm_startup(char* arg)
383 {
384     sendAdminES(Z_ESAdminOriginPartToKeep_start, NULL);
385     return 2;
386 }
387 #endif