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