2 * Copyright (c) 1998-2005, Index Data.
3 * See the file LICENSE for details.
5 * $Id: yaz-socket-manager.cpp,v 1.31 2005-01-14 10:13:50 adam Exp $
15 #include <sys/types.h>
26 #include <yaz++/socket-manager.h>
28 Yaz_SocketManager::YazSocketEntry **Yaz_SocketManager::lookupObserver(
29 IYazSocketObserver *observer)
33 for (se = &m_observers; *se; se = &(*se)->next)
34 if ((*se)->observer == observer)
39 void Yaz_SocketManager::addObserver(int fd, IYazSocketObserver *observer)
43 se = *lookupObserver(observer);
46 se = new YazSocketEntry;
47 se->next= m_observers;
49 se->observer = observer;
53 se->last_activity = 0;
57 void Yaz_SocketManager::deleteObserver(IYazSocketObserver *observer)
59 YazSocketEntry **se = lookupObserver(observer);
62 removeEvent (observer);
63 YazSocketEntry *se_tmp = *se;
69 void Yaz_SocketManager::deleteObservers()
71 YazSocketEntry *se = m_observers;
75 YazSocketEntry *se_next = se->next;
82 void Yaz_SocketManager::maskObserver(IYazSocketObserver *observer, int mask)
86 yaz_log(m_log, "obs=%p read=%d write=%d except=%d", observer,
87 mask & YAZ_SOCKET_OBSERVE_READ,
88 mask & YAZ_SOCKET_OBSERVE_WRITE,
89 mask & YAZ_SOCKET_OBSERVE_EXCEPT);
91 se = *lookupObserver(observer);
96 void Yaz_SocketManager::timeoutObserver(IYazSocketObserver *observer,
101 se = *lookupObserver(observer);
103 se->timeout = timeout;
106 int Yaz_SocketManager::processEvent()
109 YazSocketEvent *event = getEvent();
111 yaz_log (m_log, "Yaz_SocketManager::processEvent manager=%p", this);
114 event->observer->socketNotify(event->event);
119 fd_set in, out, except;
128 time_t now = time(0);
129 for (p = m_observers; p; p = p->next)
134 if (p->mask & YAZ_SOCKET_OBSERVE_READ)
136 yaz_log (m_log, "Yaz_SocketManager::select fd=%d read", fd);
139 if (p->mask & YAZ_SOCKET_OBSERVE_WRITE)
141 yaz_log (m_log, "Yaz_SocketManager::select fd=%d write", fd);
144 if (p->mask & YAZ_SOCKET_OBSERVE_EXCEPT)
146 yaz_log (m_log, "Yaz_SocketManager::select fd=%d except", fd);
151 if (p->timeout > 0 ||
152 (p->timeout == 0 && (p->mask & YAZ_SOCKET_OBSERVE_WRITE) == 0))
155 timeout_this = p->timeout;
156 if (p->last_activity)
157 timeout_this -= now - p->last_activity;
159 p->last_activity = now;
160 if (timeout_this < 0 || timeout_this > 2147483646)
162 if (timeout == -1 || timeout_this < timeout)
163 timeout = timeout_this;
164 p->timeout_this = timeout_this;
165 yaz_log (m_log, "Yaz_SocketManager::select timeout_this=%d",
171 yaz_log (m_log, "no pending events return 0");
173 yaz_log (m_log, "no observers");
181 yaz_log (m_log, "Yaz_SocketManager::select begin no=%d timeout=%d",
184 while ((res = select(max + 1, &in, &out, &except,
185 timeout== -1 ? 0 : &to)) < 0)
188 yaz_log(YLOG_ERRNO|YLOG_WARN, "select");
189 yaz_log(YLOG_WARN, "errno=%d max=%d timeout=%d",
190 errno, max, timeout);
194 yaz_log(m_log, "select returned res=%d", res);
196 for (p = m_observers; p; p = p->next)
200 if (FD_ISSET(fd, &in))
201 mask |= YAZ_SOCKET_OBSERVE_READ;
203 if (FD_ISSET(fd, &out))
204 mask |= YAZ_SOCKET_OBSERVE_WRITE;
206 if (FD_ISSET(fd, &except))
207 mask |= YAZ_SOCKET_OBSERVE_EXCEPT;
211 YazSocketEvent *event = new YazSocketEvent;
212 p->last_activity = now;
213 event->observer = p->observer;
217 yaz_log (m_log, "putEvent I/O mask=%d", mask);
219 else if (res == 0 && p->timeout_this == timeout)
221 YazSocketEvent *event = new YazSocketEvent;
222 assert (p->last_activity);
223 yaz_log (m_log, "putEvent timeout fd=%d, now = %ld last_activity=%ld timeout=%d",
224 p->fd, now, p->last_activity, p->timeout);
225 p->last_activity = now;
226 event->observer = p->observer;
227 event->event = YAZ_SOCKET_OBSERVE_TIMEOUT;
231 if ((event = getEvent()))
233 event->observer->socketNotify(event->event);
237 yaz_log(YLOG_WARN, "unhandled event in processEvent res=%d", res);
242 // n p n p ...... n p n p
245 void Yaz_SocketManager::putEvent(YazSocketEvent *event)
247 // put in back of queue
250 m_queue_back->prev = event;
251 assert (m_queue_front);
255 assert (!m_queue_front);
256 m_queue_front = event;
258 event->next = m_queue_back;
260 m_queue_back = event;
263 Yaz_SocketManager::YazSocketEvent *Yaz_SocketManager::getEvent()
265 // get from front of queue
266 YazSocketEvent *event = m_queue_front;
269 assert (m_queue_back);
270 m_queue_front = event->prev;
273 assert (m_queue_back);
274 m_queue_front->next = 0;
281 void Yaz_SocketManager::removeEvent(IYazSocketObserver *observer)
283 YazSocketEvent *ev = m_queue_back;
286 YazSocketEvent *ev_next = ev->next;
287 if (observer == ev->observer)
290 ev->prev->next = ev->next;
292 m_queue_back = ev->next;
294 ev->next->prev = ev->prev;
296 m_queue_front = ev->prev;
303 Yaz_SocketManager::Yaz_SocketManager()
311 Yaz_SocketManager::~Yaz_SocketManager()