New handler for old version item update for server:
[yazpp-moved-to-github.git] / src / yaz-my-server.cpp
1 /*
2  * Copyright (c) 1998-2001, Index Data.
3  * See the file LICENSE for details.
4  * 
5  * $Log: yaz-my-server.cpp,v $
6  * Revision 1.6  2001-05-17 14:18:03  adam
7  * New handler for old version item update for server:
8  *  void update_service0 (Z_ExtendedServicesRequest *req,
9  *                        Z_IU0Update *io, Z_ExtendedServicesResponse *res)
10  *
11  * Revision 1.5  2001/05/03 12:39:39  adam
12  * Added Update server service.
13  *
14  * Revision 1.4  2001/04/05 13:09:44  adam
15  * Removed ursula dependancy.
16  *
17  * Revision 1.3  2001/04/04 14:02:49  adam
18  * URSULA / Z-ruth service.
19  *
20  * Revision 1.2  2001/03/29 15:14:26  adam
21  * Minor updates.
22  *
23  * Revision 1.1  2001/03/27 14:47:45  adam
24  * New server facility scheme.
25  *
26  * Revision 1.15  2001/03/26 14:43:49  adam
27  * New threaded PDU association.
28  *
29  * Revision 1.14  2000/11/01 14:22:59  adam
30  * Added fd parameter for method IYaz_PDU_Observer::clone.
31  *
32  * Revision 1.13  2000/10/11 11:58:16  adam
33  * Moved header files to include/yaz++. Switched to libtool and automake.
34  * Configure script creates yaz++-config script.
35  *
36  * Revision 1.12  2000/09/21 21:43:20  adam
37  * Better high-level server API.
38  *
39  * Revision 1.11  2000/09/12 16:23:49  adam
40  * Updated server example.
41  *
42  * Revision 1.10  2000/09/12 16:04:17  adam
43  * Added comstack method for Yaz_PDU_Assoc..
44  *
45  * Revision 1.9  2000/09/12 12:09:53  adam
46  * More work on high-level server.
47  *
48  * Revision 1.8  2000/09/08 10:23:42  adam
49  * Added skeleton of yaz-z-server.
50  *
51  * Revision 1.7  1999/12/06 13:52:45  adam
52  * Modified for new location of YAZ header files. Experimental threaded
53  * operation.
54  *
55  * Revision 1.6  1999/04/21 12:09:01  adam
56  * Many improvements. Modified to proxy server to work with "sessions"
57  * based on cookies.
58  *
59  * Revision 1.5  1999/04/09 11:46:57  adam
60  * Added object Yaz_Z_Assoc. Much more functional client.
61  *
62  * Revision 1.4  1999/03/23 14:17:57  adam
63  * More work on timeout handling. Work on yaz-client.
64  *
65  * Revision 1.3  1999/02/02 14:01:22  adam
66  * First WIN32 port of YAZ++.
67  *
68  * Revision 1.2  1999/01/28 13:08:47  adam
69  * Yaz_PDU_Assoc better encapsulated. Memory leak fix in
70  * yaz-socket-manager.cc.
71  *
72  * Revision 1.1.1.1  1999/01/28 09:41:07  adam
73  * First implementation of YAZ++.
74  *
75  */
76
77 #include <yaz/log.h>
78 #include <yaz/options.h>
79 #include <yaz++/yaz-z-server.h>
80 #include <yaz++/yaz-pdu-assoc.h>
81 #include <yaz++/yaz-socket-manager.h>
82
83 class MyILL : public Yaz_Facility_ILL {
84 public:
85     void ill_service (Z_ExtendedServicesRequest *req,
86                       Z_ItemOrder *io,
87                       Z_ExtendedServicesResponse *res);
88 };
89
90 class MyUpdate : public Yaz_Facility_Update {
91 public:
92     void update_service (Z_ExtendedServicesRequest *req,
93                          Z_IUUpdate *io,
94                          Z_ExtendedServicesResponse *res);
95     void update_service0 (Z_ExtendedServicesRequest *req,
96                          Z_IU0Update *io,
97                          Z_ExtendedServicesResponse *res);
98 };
99
100
101 class MyRetrieval : public Yaz_Facility_Retrieval, Yaz_USMARC {
102 public:
103     int sr_init (Z_InitRequest *initRequest,
104                  Z_InitResponse *initResponse);
105     void sr_search (Z_SearchRequest *searchRequest,
106                         Z_SearchResponse *searchResponse);
107     void sr_present (Z_PresentRequest *presentRequest,
108                          Z_PresentResponse *presentResponse);
109     void sr_record (const char *resultSetName,
110                     int position,
111                     int *format,
112                     Z_RecordComposition *comp,
113                     Z_NamePlusRecord *namePlusRecord,
114                     Z_Records *records);
115 };
116
117 #if HAVE_YAZ_URSULA_H
118 class MyUrsula : public Yaz_Facility_Ursula {
119 public:
120     void ursula_service (Z_ExtendedServicesRequest *req,
121                          Z_UrsPDU *u,
122                          Z_ExtendedServicesResponse *res);
123 };
124 #endif
125
126 class MyServer : public Yaz_Z_Server {
127 public:
128     ~MyServer();
129     MyServer(IYaz_PDU_Observable *the_PDU_Observable);
130     IYaz_PDU_Observer* sessionNotify(IYaz_PDU_Observable *the_PDU_Observable,
131                                      int fd);
132     void failNotify();
133     void timeoutNotify();
134     void connectNotify();
135
136 private:
137     MyRetrieval m_retrieval;
138     MyILL       m_ill;
139     MyUpdate    m_update;
140 #if HAVE_YAZ_URSULA_H
141     MyUrsula    m_ursula;
142 #endif
143     int m_no;
144 };
145
146 void MyILL::ill_service (Z_ExtendedServicesRequest *req,
147                          Z_ItemOrder *io,
148                          Z_ExtendedServicesResponse *res)
149 {
150     yaz_log (LOG_LOG, "MyServer::ill_service");
151 }
152
153 void MyUpdate::update_service (Z_ExtendedServicesRequest *req,
154                            Z_IUUpdate *io,
155                            Z_ExtendedServicesResponse *res)
156 {
157     yaz_log (LOG_LOG, "MyServer::update_service (v1.1)");
158 }
159
160 void MyUpdate::update_service0 (Z_ExtendedServicesRequest *req,
161                            Z_IU0Update *io,
162                                 Z_ExtendedServicesResponse *res)
163 {
164     yaz_log (LOG_LOG, "MyServer::update_service (v1.0)");
165 }
166
167
168 #if HAVE_YAZ_URSULA_H
169 void MyUrsula::ursula_service (Z_ExtendedServicesRequest *req,
170                                Z_UrsPDU *u,
171                                Z_ExtendedServicesResponse *res)
172 {
173     yaz_log (LOG_LOG, "MyServer::ursula_service");
174     switch (u->which)
175     {
176     case  Z_UrsPDU_request:
177         yaz_log(LOG_LOG, "request");
178         if (u->u.request->libraryNo)
179             yaz_log (LOG_LOG, "libraryNo: %s", u->u.request->libraryNo);
180         break;
181     case  Z_UrsPDU_update:
182         yaz_log(LOG_LOG, "request");
183         break;
184     case  Z_UrsPDU_reservation:
185         yaz_log(LOG_LOG, "request");
186         break;
187     case  Z_UrsPDU_renewal:
188         yaz_log(LOG_LOG, "request");
189         break;
190     default:
191         yaz_log(LOG_LOG, "unknown");
192         break;
193     }
194 }
195 #endif
196
197 int MyRetrieval::sr_init (Z_InitRequest *initRequest,
198                        Z_InitResponse *initResponse)
199 {
200     yaz_log (LOG_LOG, "MyServer::sr_init");
201     return 1;
202 }
203
204 void MyRetrieval::sr_search (Z_SearchRequest *searchRequest,
205                              Z_SearchResponse *searchResponse)
206 {
207     yaz_log (LOG_LOG, "MyServer::recv_Z_search");
208     if (searchRequest->query->which == Z_Query_type_1)
209     {
210         Z_RPNStructure *s = searchRequest->query->u.type_1->RPNStructure;
211         if (s->which == Z_RPNStructure_simple &&
212             s->u.simple->which == Z_Operand_APT &&
213             s->u.simple->u.attributesPlusTerm->term->which == Z_Term_general)
214         {
215             Odr_oct *term = s->u.simple->u.attributesPlusTerm->term->u.general;
216             char *str = (char *) odr_malloc (odr_encode(), term->len+1);
217             if (term->len)
218                 memcpy (str, term->buf, term->len);
219             str[term->len] = '\0';
220             *searchResponse->resultCount = atoi(str);
221         }
222     }
223 }
224
225 void MyRetrieval::sr_present (Z_PresentRequest *presentRequest,
226                                Z_PresentResponse *presentResponse)
227 {
228     yaz_log (LOG_LOG, "MyServer::recv_Z_present");
229 }
230
231 void MyRetrieval::sr_record (const char *resultSetName,
232                              int position,
233                              int *format,
234                              Z_RecordComposition *comp,
235                              Z_NamePlusRecord *namePlusRecord,
236                              Z_Records *records)
237 {
238     yaz_log (LOG_LOG, "MyServer::recv_Z_record");
239     const char *rec = get_record(position);
240     create_databaseRecord (odr_encode(), namePlusRecord, 0, VAL_USMARC, rec,
241                            strlen(rec));
242 }
243
244 MyServer::~MyServer()
245 {
246 }
247
248 IYaz_PDU_Observer *MyServer::sessionNotify(
249     IYaz_PDU_Observable *the_PDU_Observable, int fd)
250 {
251     MyServer *new_server;
252     m_no++;
253     new_server = new MyServer(the_PDU_Observable);
254     new_server->timeout(900);
255     new_server->facility_add(&new_server->m_retrieval, "my sr");
256     new_server->facility_add(&new_server->m_ill, "my ill");
257     new_server->facility_add(&new_server->m_update, "my update");
258 #if HAVE_YAZ_URSULA_H
259     new_server->facility_add(&new_server->m_ursula, "my ursula");
260 #endif
261
262     new_server->set_APDU_log(get_APDU_log());
263
264     return new_server;
265 }
266
267 MyServer::MyServer(IYaz_PDU_Observable *the_PDU_Observable) :
268     Yaz_Z_Server (the_PDU_Observable)
269 {
270     m_no = 0;
271 }
272
273 void MyServer::timeoutNotify()
274 {
275     yaz_log (LOG_LOG, "connection timed out");
276     delete this;
277 }
278
279 void MyServer::failNotify()
280 {
281     yaz_log (LOG_LOG, "connection closed by client");
282     delete this;
283 }
284
285 void MyServer::connectNotify()
286 {
287 }
288
289
290 void usage(char *prog)
291 {
292     fprintf (stderr, "%s: [-a log] [-v level] [-T] @:port\n", prog);
293     exit (1);
294 }
295
296 int main(int argc, char **argv)
297 {
298     int thread_flag = 0;
299     char *arg;
300     char *prog = *argv;
301     char *addr = "tcp:@:9999";
302     char *apdu_log = 0;
303     
304     Yaz_SocketManager mySocketManager;
305     
306     Yaz_PDU_Assoc *my_PDU_Assoc = 0;
307     
308     MyServer *z = 0;
309     int ret;
310     
311     while ((ret = options("a:v:T", argv, argc, &arg)) != -2)
312     {
313         switch (ret)
314         {
315         case 0:
316             addr = xstrdup(arg);
317             break;
318         case 'a':
319             apdu_log = xstrdup(arg);
320             break;
321         case 'v':
322             yaz_log_init_level (yaz_log_mask_str(arg));
323             break;
324         case 'T':
325             thread_flag = 1;
326             break;
327         default:
328             usage(prog);
329             return 1;
330         }
331     }
332     if (thread_flag)
333         my_PDU_Assoc = new Yaz_PDU_AssocThread(&mySocketManager);
334     else
335         my_PDU_Assoc = new Yaz_PDU_Assoc(&mySocketManager);
336     
337     z = new MyServer(my_PDU_Assoc);
338     z->server(addr);
339     if (apdu_log)
340     {
341         yaz_log (LOG_LOG, "set_APDU_log %s", apdu_log);
342         z->set_APDU_log(apdu_log);
343     }
344
345     while (mySocketManager.processEvent() > 0)
346         ;
347     delete z;
348     return 0;
349 }