Handle present out of range better in sample 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  * $Id: yaz-my-server.cpp,v 1.16 2005-05-17 13:00:56 adam Exp $
6  */
7
8 #include <stdlib.h>
9 #include <yaz/log.h>
10 #include <yaz/diagbib1.h>
11 #include <yaz/options.h>
12 #include <yaz++/z-server.h>
13 #include <yaz++/pdu-assoc.h>
14 #include <yaz++/socket-manager.h>
15
16 class MyILL : public Yaz_Facility_ILL {
17 public:
18     void ill_service (Z_ExtendedServicesRequest *req,
19                       Z_ItemOrder *io,
20                       Z_ExtendedServicesResponse *res);
21 };
22
23 class MyUpdate : public Yaz_Facility_Update {
24 public:
25     void update_service (Z_ExtendedServicesRequest *req,
26                          Z_IUUpdate *io,
27                          Z_ExtendedServicesResponse *res);
28     void update_service0 (Z_ExtendedServicesRequest *req,
29                          Z_IU0Update *io,
30                          Z_ExtendedServicesResponse *res);
31 };
32
33
34 class MyRetrieval : public Yaz_Facility_Retrieval, Yaz_USMARC {
35 public:
36     int sr_init (Z_InitRequest *initRequest,
37                  Z_InitResponse *initResponse);
38     void sr_search (Z_SearchRequest *searchRequest,
39                         Z_SearchResponse *searchResponse);
40     void sr_present (Z_PresentRequest *presentRequest,
41                          Z_PresentResponse *presentResponse);
42     void sr_record (const char *resultSetName,
43                     int position,
44                     int *format,
45                     Z_RecordComposition *comp,
46                     Z_NamePlusRecord *namePlusRecord,
47                     Z_Records *records);
48 };
49
50 class MyServer : public Yaz_Z_Server {
51 public:
52     ~MyServer();
53     MyServer(IYaz_PDU_Observable *the_PDU_Observable);
54     IYaz_PDU_Observer* sessionNotify(IYaz_PDU_Observable *the_PDU_Observable,
55                                      int fd);
56     void failNotify();
57     void timeoutNotify();
58     void connectNotify();
59
60 private:
61     MyRetrieval m_retrieval;
62     MyILL       m_ill;
63     MyUpdate    m_update;
64     int m_no;
65 };
66
67 void MyILL::ill_service (Z_ExtendedServicesRequest *req,
68                          Z_ItemOrder *io,
69                          Z_ExtendedServicesResponse *res)
70 {
71     yaz_log (YLOG_LOG, "MyServer::ill_service");
72 }
73
74 void MyUpdate::update_service (Z_ExtendedServicesRequest *req,
75                            Z_IUUpdate *io,
76                            Z_ExtendedServicesResponse *res)
77 {
78     yaz_log (YLOG_LOG, "MyServer::update_service (v1.1)");
79 }
80
81 void MyUpdate::update_service0 (Z_ExtendedServicesRequest *req,
82                            Z_IU0Update *io,
83                                 Z_ExtendedServicesResponse *res)
84 {
85     yaz_log (YLOG_LOG, "MyServer::update_service (v1.0)");
86 }
87
88 int MyRetrieval::sr_init (Z_InitRequest *initRequest,
89                        Z_InitResponse *initResponse)
90 {
91     yaz_log (YLOG_LOG, "MyServer::sr_init");
92     return 1;
93 }
94
95 void MyRetrieval::sr_search (Z_SearchRequest *searchRequest,
96                              Z_SearchResponse *searchResponse)
97 {
98     yaz_log (YLOG_LOG, "MyServer::recv_Z_search");
99     if (searchRequest->query->which == Z_Query_type_1)
100     {
101         Z_RPNStructure *s = searchRequest->query->u.type_1->RPNStructure;
102         if (s->which == Z_RPNStructure_simple &&
103             s->u.simple->which == Z_Operand_APT &&
104             s->u.simple->u.attributesPlusTerm->term->which == Z_Term_general)
105         {
106             Odr_oct *term = s->u.simple->u.attributesPlusTerm->term->u.general;
107             char *str = (char *) odr_malloc (odr_encode(), term->len+1);
108             if (term->len)
109                 memcpy (str, term->buf, term->len);
110             str[term->len] = '\0';
111             *searchResponse->resultCount = atoi(str);
112         }
113     }
114 }
115
116 void MyRetrieval::sr_present (Z_PresentRequest *presentRequest,
117                                Z_PresentResponse *presentResponse)
118 {
119     yaz_log (YLOG_LOG, "MyServer::recv_Z_present");
120 }
121
122 void MyRetrieval::sr_record (const char *resultSetName,
123                              int position,
124                              int *format,
125                              Z_RecordComposition *comp,
126                              Z_NamePlusRecord *namePlusRecord,
127                              Z_Records *records)
128 {
129     yaz_log (YLOG_LOG, "MyServer::recv_Z_record");
130     const char *rec = get_record(position);
131     if (rec)
132         create_databaseRecord (odr_encode(), namePlusRecord, 0,
133                                VAL_USMARC, rec, strlen(rec));
134     else
135         create_surrogateDiagnostics(odr_encode(), namePlusRecord, 0,
136                                     YAZ_BIB1_PRESENT_REQUEST_OUT_OF_RANGE, 0);
137 }
138
139 MyServer::~MyServer()
140 {
141 }
142
143 IYaz_PDU_Observer *MyServer::sessionNotify(
144     IYaz_PDU_Observable *the_PDU_Observable, int fd)
145 {
146     MyServer *new_server;
147     m_no++;
148     new_server = new MyServer(the_PDU_Observable);
149     new_server->timeout(900);
150     new_server->facility_add(&new_server->m_retrieval, "my sr");
151     new_server->facility_add(&new_server->m_ill, "my ill");
152     new_server->facility_add(&new_server->m_update, "my update");
153     new_server->set_APDU_log(get_APDU_log());
154
155     return new_server;
156 }
157
158 MyServer::MyServer(IYaz_PDU_Observable *the_PDU_Observable) :
159     Yaz_Z_Server (the_PDU_Observable)
160 {
161     m_no = 0;
162 }
163
164 void MyServer::timeoutNotify()
165 {
166     yaz_log (YLOG_LOG, "connection timed out");
167     delete this;
168 }
169
170 void MyServer::failNotify()
171 {
172     yaz_log (YLOG_LOG, "connection closed by client");
173     delete this;
174 }
175
176 void MyServer::connectNotify()
177 {
178 }
179
180 void usage(const char *prog)
181 {
182     fprintf (stderr, "%s: [-a log] [-v level] [-T] @:port\n", prog);
183     exit (1);
184 }
185
186 int main(int argc, char **argv)
187 {
188     int thread_flag = 0;
189     char *arg;
190     char *prog = *argv;
191     const char *addr = "tcp:@:9999";
192     char *apdu_log = 0;
193     
194     Yaz_SocketManager mySocketManager;
195     
196     Yaz_PDU_Assoc *my_PDU_Assoc = 0;
197     
198     MyServer *z = 0;
199     int ret;
200     
201     while ((ret = options("a:v:T", argv, argc, &arg)) != -2)
202     {
203         switch (ret)
204         {
205         case 0:
206             addr = xstrdup(arg);
207             break;
208         case 'a':
209             apdu_log = xstrdup(arg);
210             break;
211         case 'v':
212             yaz_log_init_level (yaz_log_mask_str(arg));
213             break;
214         case 'T':
215             thread_flag = 1;
216             break;
217         default:
218             usage(prog);
219             return 1;
220         }
221     }
222 #if YAZ_POSIX_THREADS
223     if (thread_flag)
224         my_PDU_Assoc = new Yaz_PDU_AssocThread(&mySocketManager);
225     else
226         my_PDU_Assoc = new Yaz_PDU_Assoc(&mySocketManager);
227 #else
228     my_PDU_Assoc = new Yaz_PDU_Assoc(&mySocketManager);
229 #endif
230     
231     z = new MyServer(my_PDU_Assoc);
232     z->server(addr);
233     if (apdu_log)
234     {
235         yaz_log (YLOG_LOG, "set_APDU_log %s", apdu_log);
236         z->set_APDU_log(apdu_log);
237     }
238
239     while (mySocketManager.processEvent() > 0)
240         ;
241     delete z;
242     return 0;
243 }