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