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