2 * Copyright (c) 1998-2005, Index Data.
3 * See the file LICENSE for details.
5 * $Id: yaz-socket-manager.cpp,v 1.38 2007-11-09 22:10:10 adam Exp $
12 #include <sys/types.h>
24 #include <yazpp/socket-manager.h>
27 using namespace yazpp_1;
29 SocketManager::SocketEntry **SocketManager::lookupObserver(
30 ISocketObserver *observer)
34 for (se = &m_observers; *se; se = &(*se)->next)
35 if ((*se)->observer == observer)
40 void SocketManager::addObserver(int fd, ISocketObserver *observer)
44 se = *lookupObserver(observer);
48 se->next= m_observers;
50 se->observer = observer;
54 se->last_activity = 0;
58 void SocketManager::deleteObserver(ISocketObserver *observer)
60 SocketEntry **se = lookupObserver(observer);
63 removeEvent (observer);
64 SocketEntry *se_tmp = *se;
70 void SocketManager::deleteObservers()
72 SocketEntry *se = m_observers;
76 SocketEntry *se_next = se->next;
83 void SocketManager::maskObserver(ISocketObserver *observer, int mask)
87 yaz_log(m_log, "obs=%p read=%d write=%d except=%d", observer,
88 mask & SOCKET_OBSERVE_READ,
89 mask & SOCKET_OBSERVE_WRITE,
90 mask & SOCKET_OBSERVE_EXCEPT);
92 se = *lookupObserver(observer);
97 void SocketManager::timeoutObserver(ISocketObserver *observer,
102 se = *lookupObserver(observer);
104 se->timeout = timeout;
107 int SocketManager::processEvent()
110 SocketEvent *event = getEvent();
112 yaz_log (m_log, "SocketManager::processEvent manager=%p", this);
115 event->observer->socketNotify(event->event);
121 time_t now = time(0);
124 for (p = m_observers; p; p = p->next)
129 struct yaz_poll_fd *fds = new yaz_poll_fd [no_fds];
130 for (i = 0, p = m_observers; p; p = p->next, i++)
134 if (p->mask & SOCKET_OBSERVE_READ)
135 input_mask += yaz_poll_read;
136 if (p->mask & SOCKET_OBSERVE_WRITE)
137 input_mask += yaz_poll_write;
138 if (p->mask & SOCKET_OBSERVE_EXCEPT)
139 input_mask += yaz_poll_except;
140 if (p->timeout > 0 ||
141 (p->timeout == 0 && (p->mask & SOCKET_OBSERVE_WRITE) == 0))
144 timeout_this = p->timeout;
145 if (p->last_activity)
146 timeout_this -= now - p->last_activity;
148 p->last_activity = now;
149 if (timeout_this < 0 || timeout_this > 2147483646)
151 if (timeout == -1 || timeout_this < timeout)
152 timeout = timeout_this;
153 p->timeout_this = timeout_this;
154 yaz_log (m_log, "SocketManager::select timeout_this=%d",
158 p->timeout_this = -1;
159 fds[i].input_mask = (enum yaz_poll_mask) input_mask;
163 while ((res = yaz_poll(fds, no_fds, timeout, 0)) < 0)
167 yaz_log(YLOG_ERRNO|YLOG_WARN, "yaz_poll");
168 yaz_log(YLOG_WARN, "errno=%d timeout=%d", errno, timeout);
174 yaz_log(m_log, "select returned res=%d", res);
176 for (i = 0, p = m_observers; p; p = p->next, i++)
178 enum yaz_poll_mask output_mask = fds[i].output_mask;
181 if (output_mask & yaz_poll_read)
182 mask |= SOCKET_OBSERVE_READ;
184 if (output_mask & yaz_poll_write)
185 mask |= SOCKET_OBSERVE_WRITE;
187 if (output_mask & yaz_poll_except)
188 mask |= SOCKET_OBSERVE_EXCEPT;
192 SocketEvent *event = new SocketEvent;
193 p->last_activity = now;
194 event->observer = p->observer;
198 yaz_log (m_log, "putEvent I/O mask=%d", mask);
200 else if (res == 0 && p->timeout_this == timeout)
202 SocketEvent *event = new SocketEvent;
203 assert (p->last_activity);
204 yaz_log (m_log, "putEvent timeout fd=%d, now = %ld last_activity=%ld timeout=%d",
205 p->fd, now, p->last_activity, p->timeout);
206 p->last_activity = now;
207 event->observer = p->observer;
208 event->event = SOCKET_OBSERVE_TIMEOUT;
213 if ((event = getEvent()))
215 event->observer->socketNotify(event->event);
219 yaz_log(YLOG_WARN, "unhandled event in processEvent res=%d", res);
224 // n p n p ...... n p n p
227 void SocketManager::putEvent(SocketEvent *event)
229 // put in back of queue
232 m_queue_back->prev = event;
233 assert (m_queue_front);
237 assert (!m_queue_front);
238 m_queue_front = event;
240 event->next = m_queue_back;
242 m_queue_back = event;
245 SocketManager::SocketEvent *SocketManager::getEvent()
247 // get from front of queue
248 SocketEvent *event = m_queue_front;
251 assert (m_queue_back);
252 m_queue_front = event->prev;
255 assert (m_queue_back);
256 m_queue_front->next = 0;
263 void SocketManager::removeEvent(ISocketObserver *observer)
265 SocketEvent *ev = m_queue_back;
268 SocketEvent *ev_next = ev->next;
269 if (observer == ev->observer)
272 ev->prev->next = ev->next;
274 m_queue_back = ev->next;
276 ev->next->prev = ev->prev;
278 m_queue_front = ev->prev;
285 SocketManager::SocketManager()
293 SocketManager::~SocketManager()
300 * indent-tabs-mode: nil
302 * vim: shiftwidth=4 tabstop=8 expandtab