Separate malloc debug library. Removal of ASN_COMPILED-#ifdefs.
[yaz-moved-to-github.git] / client / admin.c
1 /*
2  * Copyright (c) 1995-2001, Index Data
3  * See the file LICENSE for details.
4  *
5  * $Id: admin.c,v 1.11 2001-11-13 23:00:42 adam Exp $
6  */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <time.h>
11 #include <assert.h>
12
13 #ifdef WIN32
14
15 #else
16 #include <dirent.h>
17 #include <fnmatch.h>
18 #include <sys/stat.h>
19 #endif
20
21 #include <yaz/yaz-util.h>
22
23 #include <yaz/tcpip.h>
24 #ifdef USE_XTIMOSI
25 #include <yaz/xmosi.h>
26 #endif
27
28 #include <yaz/proto.h>
29 #include <yaz/marcdisp.h>
30 #include <yaz/diagbib1.h>
31
32 #include <yaz/pquery.h>
33
34
35 /* Helper functions to get to various statics in the client */
36 ODR getODROutputStream();
37 void send_apdu(Z_APDU *a);
38
39 extern char *databaseNames[];
40 extern int num_databaseNames;
41
42 int sendAdminES(int type, char* param1)
43 {
44     ODR out = getODROutputStream();
45     char *dbname = odr_strdup (out, databaseNames[0]);
46
47     /* Type: 1=reindex, 2=truncate, 3=delete, 4=create, 5=import, 6=refresh, 7=commit */
48     Z_APDU *apdu = zget_APDU(out, Z_APDU_extendedServicesRequest );
49     Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest;
50     Z_External *r;
51     int oid[OID_SIZE];
52     Z_ESAdminOriginPartToKeep  *toKeep;
53     Z_ESAdminOriginPartNotToKeep  *notToKeep;
54     oident update_oid;
55     printf ("Admin request\n");
56     fflush(stdout);
57
58     /* Set up the OID for the external */
59     update_oid.proto = PROTO_Z3950;
60     update_oid.oclass = CLASS_EXTSERV;
61     update_oid.value = VAL_ADMINSERVICE;
62
63     oid_ent_to_oid (&update_oid, oid);
64     req->packageType = odr_oiddup(out,oid);
65     req->packageName = "1.Extendedserveq";
66
67     /* Allocate the external */
68     r = req->taskSpecificParameters = (Z_External *) odr_malloc (out, sizeof(*r));
69     r->direct_reference = odr_oiddup(out,oid);
70     r->indirect_reference = 0;
71     r->descriptor = 0;
72     r->which = Z_External_ESAdmin;
73     r->u.adminService = (Z_Admin *) odr_malloc(out, sizeof(*r->u.adminService));
74     r->u.adminService->which = Z_Admin_esRequest;
75     r->u.adminService->u.esRequest = (Z_AdminEsRequest *) odr_malloc(out, sizeof(*r->u.adminService->u.esRequest));
76
77     toKeep = r->u.adminService->u.esRequest->toKeep = (Z_ESAdminOriginPartToKeep *) 
78                      odr_malloc(out, sizeof(*r->u.adminService->u.esRequest->toKeep));
79
80     toKeep->which=type;
81     toKeep->databaseName = dbname;
82     switch ( type )
83     {
84     case Z_ESAdminOriginPartToKeep_reIndex:
85         toKeep->u.reIndex=odr_nullval();
86         break;
87         
88     case Z_ESAdminOriginPartToKeep_truncate:
89         toKeep->u.truncate=odr_nullval();
90         break;
91     case Z_ESAdminOriginPartToKeep_drop:
92         toKeep->u.drop=odr_nullval();
93         break;
94     case Z_ESAdminOriginPartToKeep_create:
95         toKeep->u.create=odr_nullval();
96         break;
97     case Z_ESAdminOriginPartToKeep_import:
98         toKeep->u.import = (Z_ImportParameters*)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(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(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(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(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 #ifdef WIN32
181 int cmd_adm_import(char *arg)
182 {
183     printf ("not available on WIN32\n");
184     return 0;
185 }
186
187 #else
188
189 int cmd_adm_import(char *arg)
190 {
191     char type_str[20], dir_str[1024], pattern_str[1024];
192     char *cp;
193     char *sep = "/";
194     DIR *dir;
195     struct dirent *ent;
196     int chunk = 10;
197     Z_APDU *apdu = 0;
198     Z_Segment *segment = 0;
199     ODR out = getODROutputStream();
200
201     if (arg && sscanf (arg, "%19s %1023s %1023s", type_str,
202                        dir_str, pattern_str) != 3)
203         return 0;
204     if (num_databaseNames != 1)
205         return 0;
206     dir = opendir(dir_str);
207     if (!dir)
208         return 0;
209     
210     sendAdminES(Z_ESAdminOriginPartToKeep_import, type_str);
211
212     printf ("sent es request\n");
213     if ((cp=strrchr(dir_str, '/')) && cp[1] == 0)
214         sep="";
215         
216     while ((ent = readdir(dir)))
217     {
218         if (fnmatch (pattern_str, ent->d_name, 0) == 0)
219         {
220             char fname[1024];
221             struct stat status;
222             FILE *inf;
223                 
224             sprintf (fname, "%s%s%s", dir_str, sep, ent->d_name);
225             stat (fname, &status);
226
227             if (S_ISREG(status.st_mode) && (inf = fopen(fname, "r")))
228             {
229                 Z_NamePlusRecord *rec;
230                 Odr_oct *oct = (Odr_oct *) odr_malloc (out, sizeof(*oct));
231
232                 if (!apdu)
233                 {
234                     apdu = zget_APDU(out, Z_APDU_segmentRequest);
235                     segment = apdu->u.segmentRequest;
236                     segment->segmentRecords = (Z_NamePlusRecord **)
237                         odr_malloc (out, chunk * sizeof(*segment->segmentRecords));
238                 }
239                 rec = (Z_NamePlusRecord *) odr_malloc (out, sizeof(*rec));
240                 rec->databaseName = 0;
241                 rec->which = Z_NamePlusRecord_intermediateFragment;
242                 rec->u.intermediateFragment = (Z_FragmentSyntax *)
243                     odr_malloc (out, sizeof(*rec->u.intermediateFragment));
244                 rec->u.intermediateFragment->which =
245                     Z_FragmentSyntax_notExternallyTagged;
246                 rec->u.intermediateFragment->u.notExternallyTagged = oct;
247                 
248                 oct->len = oct->size = status.st_size;
249                 oct->buf = (unsigned char *) odr_malloc (out, oct->size);
250                 fread (oct->buf, 1, oct->size, inf);
251                 fclose (inf);
252                 
253                 segment->segmentRecords[segment->num_segmentRecords++] = rec;
254
255                 if (segment->num_segmentRecords == chunk)
256                 {
257                     send_apdu (apdu);
258                     apdu = 0;
259                 }
260             }   
261         }
262     }
263     if (apdu)
264         send_apdu(apdu);
265     apdu = zget_APDU(out, Z_APDU_segmentRequest);
266     send_apdu (apdu);
267     closedir(dir);
268     return 2;
269 }
270 #endif
271
272 int cmd_adm_import2(char* arg)
273 {
274    /* Buffer for reading chunks of data from import file */
275     char chunk_buffer[8192];
276     
277     if ( arg )
278     {
279         char rectype_buff[32];
280         char filename_buff[32];
281         FILE* pImportFile = NULL;
282
283         if (sscanf (arg, "%s %s", rectype_buff, filename_buff) != 3)
284         {
285             printf("Must specify database-name, record-type and filename for import\n");
286             return 0;
287         }
288
289         /* Attempt to open the file */
290
291         pImportFile = fopen(filename_buff,"r");
292
293         /* This chunk of code should move into client.c sometime soon for sending files via the update es */
294         /* This function will then refer to the standard client.c one for uploading a file using es update */
295         if ( pImportFile )
296         {
297             int iTotalWritten = 0;
298
299             /* We opened the import file without problems... So no we send the es request, ready to 
300                start sending fragments of the import file as segment messages */
301             sendAdminES(Z_ESAdminOriginPartToKeep_import, rectype_buff);
302
303             while ( ! feof(pImportFile ) )
304             {
305                 /* Read buffer_size bytes from the file */
306                 size_t num_items = fread((void*)chunk_buffer, 1, sizeof(chunk_buffer),  pImportFile);
307
308                 /* Write num_bytes of data to */
309
310                 if ( feof(pImportFile ) )
311                 {
312                     /* This is the last chunk... Write it as the last fragment */
313                     printf("Last segment of %d bytes\n", num_items);
314                 }
315                 else if ( iTotalWritten == 0 )
316                 {
317                     printf("First segment of %d bytes\n",num_items);
318                 }
319                 else
320                 {
321                     printf("Writing %d bytes\n", num_items);
322                 }
323
324                 iTotalWritten += num_items;
325             }
326         }
327         return 2;
328     }
329     return 0;
330 }
331
332 /* "Freshen" the specified database, by checking metadata records against the sources from which they were 
333    generated, and creating a new record if the source has been touched since the last extraction */
334 int cmd_adm_refresh(char* arg)
335 {
336     if ( arg )
337     {
338         sendAdminES(Z_ESAdminOriginPartToKeep_refresh, NULL);
339         return 2;
340     }
341     return 0;
342 }
343
344 /* cmd_adm_commit 
345    Make imported records a permenant & visible to the live system */
346 int cmd_adm_commit(char* arg)
347 {
348     sendAdminES(Z_ESAdminOriginPartToKeep_commit, NULL);
349     return 2;
350 }
351
352 int cmd_adm_shutdown(char* arg)
353 {
354     sendAdminES(Z_ESAdminOriginPartToKeep_shutdown, NULL);
355     return 2;
356 }
357
358 int cmd_adm_startup(char* arg)
359 {
360     sendAdminES(Z_ESAdminOriginPartToKeep_start, NULL);
361     return 2;
362 }