2 * Copyright (c) 1998-2000, Index Data.
3 * See the file LICENSE for details.
5 * $Log: yaz-socket-manager.cpp,v $
6 * Revision 1.16 2001-08-13 16:39:12 adam
7 * PDU_Assoc keeps track of children. Using yaz_log instead of logf.
9 * Revision 1.15 2001/03/26 14:43:49 adam
10 * New threaded PDU association.
12 * Revision 1.14 2000/11/20 14:17:36 adam
13 * Yet another WIN32 fix for connect notify.
15 * Revision 1.13 2000/11/20 11:27:33 adam
16 * Fixes for connect operation (timeout and notify fix).
18 * Revision 1.12 2000/10/24 12:29:57 adam
19 * Fixed bug in proxy where a Yaz_ProxyClient could be owned by
20 * two Yaz_Proxy's (fatal).
22 * Revision 1.11 2000/10/11 11:58:17 adam
23 * Moved header files to include/yaz++. Switched to libtool and automake.
24 * Configure script creates yaz++-config script.
26 * Revision 1.10 2000/09/08 10:23:42 adam
27 * Added skeleton of yaz-z-server.
29 * Revision 1.9 2000/08/07 14:19:59 adam
30 * Fixed serious bug regarding timeouts. Improved logging for proxy.
32 * Revision 1.8 1999/12/06 13:52:45 adam
33 * Modified for new location of YAZ header files. Experimental threaded
36 * Revision 1.7 1999/04/28 13:02:08 adam
37 * Added include of string.h.
39 * Revision 1.6 1999/04/21 12:09:01 adam
40 * Many improvements. Modified to proxy server to work with "sessions"
43 * Revision 1.5 1999/04/09 11:46:57 adam
44 * Added object Yaz_Z_Assoc. Much more functional client.
46 * Revision 1.4 1999/03/23 14:17:57 adam
47 * More work on timeout handling. Work on yaz-client.
49 * Revision 1.3 1999/02/02 14:01:23 adam
50 * First WIN32 port of YAZ++.
52 * Revision 1.2 1999/01/28 13:08:48 adam
53 * Yaz_PDU_Assoc better encapsulated. Memory leak fix in
54 * yaz-socket-manager.cc.
56 * Revision 1.1.1.1 1999/01/28 09:41:07 adam
57 * First implementation of YAZ++.
65 #include <sys/types.h>
72 #include <yaz++/yaz-socket-manager.h>
74 Yaz_SocketManager::YazSocketEntry **Yaz_SocketManager::lookupObserver(
75 IYazSocketObserver *observer)
79 for (se = &m_observers; *se; se = &(*se)->next)
80 if ((*se)->observer == observer)
85 void Yaz_SocketManager::addObserver(int fd, IYazSocketObserver *observer)
89 se = *lookupObserver(observer);
92 se = new YazSocketEntry;
93 se->next= m_observers;
95 se->observer = observer;
99 se->last_activity = 0;
103 void Yaz_SocketManager::deleteObserver(IYazSocketObserver *observer)
105 YazSocketEntry **se = lookupObserver(observer);
108 removeEvent (observer);
109 YazSocketEntry *se_tmp = *se;
115 void Yaz_SocketManager::deleteObservers()
117 YazSocketEntry *se = m_observers;
121 YazSocketEntry *se_next = se->next;
128 void Yaz_SocketManager::maskObserver(IYazSocketObserver *observer, int mask)
132 se = *lookupObserver(observer);
137 void Yaz_SocketManager::timeoutObserver(IYazSocketObserver *observer,
142 se = *lookupObserver(observer);
144 se->timeout = timeout;
147 int Yaz_SocketManager::processEvent()
150 YazSocketEvent *event = getEvent();
151 unsigned timeout = 0;
152 yaz_log (m_log, "Yaz_SocketManager::processEvent manager=%p", this);
155 event->observer->socketNotify(event->event);
160 fd_set in, out, except;
169 time_t now = time(0);
170 for (p = m_observers; p; p = p->next)
175 if (p->mask & YAZ_SOCKET_OBSERVE_READ)
177 yaz_log (m_log, "Yaz_SocketManager::select fd=%d read", fd);
180 if (p->mask & YAZ_SOCKET_OBSERVE_WRITE)
182 yaz_log (m_log, "Yaz_SocketManager::select fd=%d write", fd);
185 if (p->mask & YAZ_SOCKET_OBSERVE_EXCEPT)
187 yaz_log (m_log, "Yaz_SocketManager::select fd=%d except", fd);
194 unsigned timeout_this;
195 timeout_this = p->timeout;
196 if (p->last_activity)
197 timeout_this -= now - p->last_activity;
199 p->last_activity = now;
200 if (timeout_this < 1)
202 if (!timeout || timeout_this < timeout)
203 timeout = timeout_this;
208 yaz_log (m_log, "no pending events return 0");
210 yaz_log (m_log, "no observers");
218 yaz_log (m_log, "Yaz_SocketManager::select no=%d timeout=%d", no, timeout);
219 while ((res = select(max + 1, &in, &out, &except, timeout ? &to : 0)) < 0)
223 for (p = m_observers; p; p = p->next)
227 if (FD_ISSET(fd, &in))
228 mask |= YAZ_SOCKET_OBSERVE_READ;
230 if (FD_ISSET(fd, &out))
231 mask |= YAZ_SOCKET_OBSERVE_WRITE;
233 if (FD_ISSET(fd, &except))
234 mask |= YAZ_SOCKET_OBSERVE_EXCEPT;
238 YazSocketEvent *event = new YazSocketEvent;
239 p->last_activity = now;
240 event->observer = p->observer;
244 else if (p->timeout && p->last_activity &&
245 now >= p->last_activity + (int) (p->timeout))
247 YazSocketEvent *event = new YazSocketEvent;
248 yaz_log (m_log, "timeout, now = %ld last_activity=%ld timeout=%d",
249 now, p->last_activity, p->timeout);
250 p->last_activity = now;
251 event->observer = p->observer;
252 event->event = YAZ_SOCKET_OBSERVE_TIMEOUT;
256 if ((event = getEvent()))
258 event->observer->socketNotify(event->event);
266 // n p n p ...... n p n p
269 void Yaz_SocketManager::putEvent(YazSocketEvent *event)
271 // put in back of queue
274 m_queue_back->prev = event;
275 assert (m_queue_front);
279 assert (!m_queue_front);
280 m_queue_front = event;
282 event->next = m_queue_back;
284 m_queue_back = event;
287 Yaz_SocketManager::YazSocketEvent *Yaz_SocketManager::getEvent()
289 // get from front of queue
290 YazSocketEvent *event = m_queue_front;
293 assert (m_queue_back);
294 m_queue_front = event->prev;
297 assert (m_queue_back);
298 m_queue_front->next = 0;
305 void Yaz_SocketManager::removeEvent(IYazSocketObserver *observer)
307 YazSocketEvent *ev = m_queue_back;
310 YazSocketEvent *ev_next = ev->next;
311 if (observer == ev->observer)
314 ev->prev->next = ev->next;
316 m_queue_back = ev->next;
318 ev->next->prev = ev->prev;
320 m_queue_front = ev->prev;
327 Yaz_SocketManager::Yaz_SocketManager()
335 Yaz_SocketManager::~Yaz_SocketManager()