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