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