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