2 * Copyright (c) 1998-2000, Index Data.
3 * See the file LICENSE for details.
5 * $Log: yaz-socket-manager.cpp,v $
6 * Revision 1.10 2000-09-08 10:23:42 adam
7 * Added skeleton of yaz-z-server.
9 * Revision 1.9 2000/08/07 14:19:59 adam
10 * Fixed serious bug regarding timeouts. Improved logging for proxy.
12 * Revision 1.8 1999/12/06 13:52:45 adam
13 * Modified for new location of YAZ header files. Experimental threaded
16 * Revision 1.7 1999/04/28 13:02:08 adam
17 * Added include of string.h.
19 * Revision 1.6 1999/04/21 12:09:01 adam
20 * Many improvements. Modified to proxy server to work with "sessions"
23 * Revision 1.5 1999/04/09 11:46:57 adam
24 * Added object Yaz_Z_Assoc. Much more functional client.
26 * Revision 1.4 1999/03/23 14:17:57 adam
27 * More work on timeout handling. Work on yaz-client.
29 * Revision 1.3 1999/02/02 14:01:23 adam
30 * First WIN32 port of YAZ++.
32 * Revision 1.2 1999/01/28 13:08:48 adam
33 * Yaz_PDU_Assoc better encapsulated. Memory leak fix in
34 * yaz-socket-manager.cc.
36 * Revision 1.1.1.1 1999/01/28 09:41:07 adam
37 * First implementation of YAZ++.
45 #include <sys/types.h>
52 #include <yaz-socket-manager.h>
55 Yaz_SocketManager::YazSocketEntry **Yaz_SocketManager::lookupObserver(
56 IYazSocketObserver *observer)
60 for (se = &m_observers; *se; se = &(*se)->next)
61 if ((*se)->observer == observer)
66 void Yaz_SocketManager::addObserver(int fd, IYazSocketObserver *observer)
70 se = *lookupObserver(observer);
73 se = new YazSocketEntry;
74 se->next= m_observers;
76 se->observer = observer;
80 se->last_activity = 0;
84 void Yaz_SocketManager::deleteObserver(IYazSocketObserver *observer)
86 YazSocketEntry **se = lookupObserver(observer);
89 removeEvent (observer);
90 YazSocketEntry *se_tmp = *se;
96 void Yaz_SocketManager::deleteObservers()
98 YazSocketEntry *se = m_observers;
102 YazSocketEntry *se_next = se->next;
109 void Yaz_SocketManager::maskObserver(IYazSocketObserver *observer, int mask)
113 se = *lookupObserver(observer);
118 void Yaz_SocketManager::timeoutObserver(IYazSocketObserver *observer,
123 se = *lookupObserver(observer);
125 se->timeout = timeout;
128 int Yaz_SocketManager::processEvent()
131 YazSocketEvent *event = getEvent();
132 unsigned timeout = 0;
133 logf (m_log, "processEvent");
136 event->observer->socketNotify(event->event);
141 fd_set in, out, except;
150 time_t now = time(0);
151 for (p = m_observers; p; p = p->next)
156 if (p->mask & YAZ_SOCKET_OBSERVE_READ)
158 if (p->mask & YAZ_SOCKET_OBSERVE_WRITE)
160 if (p->mask & YAZ_SOCKET_OBSERVE_EXCEPT)
166 unsigned timeout_this;
167 timeout_this = p->timeout;
168 if (p->last_activity)
169 timeout_this -= now - p->last_activity;
170 if (timeout_this < 1)
172 if (!timeout || timeout_this < timeout)
173 timeout = timeout_this;
178 logf (m_log, "no pending events return 0");
180 logf (m_log, "no observers");
188 logf (m_log, "select pending=%d timeout=%d", no, timeout);
189 while ((res = select(max + 1, &in, &out, &except, timeout ? &to : 0)) < 0)
193 for (p = m_observers; p; p = p->next)
197 if (FD_ISSET(fd, &in))
198 mask |= YAZ_SOCKET_OBSERVE_READ;
200 if (FD_ISSET(fd, &out))
201 mask |= YAZ_SOCKET_OBSERVE_WRITE;
203 if (FD_ISSET(fd, &except))
204 mask |= YAZ_SOCKET_OBSERVE_EXCEPT;
208 YazSocketEvent *event = new YazSocketEvent;
209 p->last_activity = now;
210 event->observer = p->observer;
214 else if (p->timeout && p->last_activity &&
215 now >= p->last_activity + (int) (p->timeout))
217 YazSocketEvent *event = new YazSocketEvent;
218 logf (LOG_LOG, "timeout now = %ld last_activity=%ld timeout=%d",
219 now, p->last_activity, p->timeout);
220 p->last_activity = now;
221 event->observer = p->observer;
222 event->event = YAZ_SOCKET_OBSERVE_TIMEOUT;
226 if ((event = getEvent()))
228 event->observer->socketNotify(event->event);
235 void Yaz_SocketManager::putEvent(YazSocketEvent *event)
237 // put in back of queue
240 m_queue_back->prev = event;
241 assert (m_queue_front);
245 assert (!m_queue_front);
246 m_queue_front = event;
248 event->next = m_queue_back;
250 m_queue_back = event;
253 Yaz_SocketManager::YazSocketEvent *Yaz_SocketManager::getEvent()
255 // get from front of queue
256 YazSocketEvent *event = m_queue_front;
259 assert (m_queue_back);
260 m_queue_front = event->prev;
263 assert (m_queue_back);
264 m_queue_front->next = 0;
271 void Yaz_SocketManager::removeEvent(IYazSocketObserver *observer)
273 YazSocketEvent *ev = m_queue_back;
276 YazSocketEvent *ev_next = ev->next;
277 if (observer == ev->observer)
280 ev->prev->next = ev->next;
282 m_queue_back = ev->next;
284 ev->next->prev = ev->prev;
286 m_queue_front = ev->prev;
293 Yaz_SocketManager::Yaz_SocketManager()
301 Yaz_SocketManager::~Yaz_SocketManager()