version 1.116.4.2, 2007/12/14 20:47:55
|
version 1.117, 2007/02/14 05:13:59
|
|
|
{ | { |
uninitializeTickler(); | uninitializeTickler(); |
Socket::uninitializeInterface(); | Socket::uninitializeInterface(); |
PEG_TRACE_CSTRING(TRC_HTTP, Tracer::LEVEL4, |
Tracer::trace(TRC_HTTP, Tracer::LEVEL4, |
"returning from monitor destructor"); | "returning from monitor destructor"); |
} | } |
void Monitor::uninitializeTickler() | void Monitor::uninitializeTickler() |
{ | { |
PEG_TRACE_CSTRING(TRC_HTTP, Tracer::LEVEL4, "uninitializing interface"); |
Tracer::trace(TRC_HTTP, Tracer::LEVEL4, "uninitializing interface"); |
| |
try | try |
{ | { |
|
|
} | } |
catch (...) | catch (...) |
{ | { |
PEG_TRACE_CSTRING(TRC_HTTP, Tracer::LEVEL4, |
Tracer::trace(TRC_HTTP, Tracer::LEVEL4, |
"Failed to close tickle sockets"); | "Failed to close tickle sockets"); |
} | } |
| |
|
|
void Monitor::run(Uint32 milliseconds) | void Monitor::run(Uint32 milliseconds) |
{ | { |
| |
int i = 0; |
|
| |
struct timeval tv = {milliseconds/1000, milliseconds%1000*1000}; | struct timeval tv = {milliseconds/1000, milliseconds%1000*1000}; |
| |
|
|
| |
if (h._responsePending == true) | if (h._responsePending == true) |
{ | { |
PEG_TRACE((TRC_HTTP, Tracer::LEVEL4, |
Tracer::trace(TRC_HTTP, Tracer::LEVEL4, |
"Monitor::run - Ignoring connection delete request " | "Monitor::run - Ignoring connection delete request " |
"because responses are still pending. " | "because responses are still pending. " |
"connection=0x%p, socket=%d\n", | "connection=0x%p, socket=%d\n", |
(void *)&h, h.getSocket())); |
(void *)&h, h.getSocket()); |
continue; | continue; |
} | } |
h._connectionClosePending = false; | h._connectionClosePending = false; |
|
|
#endif | #endif |
_entry_mut.lock(); | _entry_mut.lock(); |
| |
struct timeval timeNow; |
|
Time::gettimeofday(&timeNow); |
|
|
|
// After enqueue a message and the autoEntryMutex has been released and | // After enqueue a message and the autoEntryMutex has been released and |
// locked again, the array of _entries can be changed. The ArrayIterator | // locked again, the array of _entries can be changed. The ArrayIterator |
// has be reset with the original _entries | // has be reset with the original _entries |
|
|
| |
if (events == PEGASUS_SOCKET_ERROR) | if (events == PEGASUS_SOCKET_ERROR) |
{ | { |
PEG_TRACE((TRC_HTTP, Tracer::LEVEL4, |
Tracer::trace(TRC_HTTP, Tracer::LEVEL4, |
"Monitor::run - errorno = %d has occurred on select.", errno)); |
"Monitor::run - errorno = %d has occurred on select.", errno); |
// The EBADF error indicates that one or more or the file | // The EBADF error indicates that one or more or the file |
// descriptions was not valid. This could indicate that | // descriptions was not valid. This could indicate that |
// the entries structure has been corrupted or that | // the entries structure has been corrupted or that |
|
|
} | } |
else if (events) | else if (events) |
{ | { |
PEG_TRACE((TRC_HTTP, Tracer::LEVEL4, |
Tracer::trace(TRC_HTTP, Tracer::LEVEL4, |
"Monitor::run select event received events = %d, monitoring %d " | "Monitor::run select event received events = %d, monitoring %d " |
"idle entries", | "idle entries", |
events, _idleEntries)); |
events, _idleEntries); |
for (int indx = 0; indx < (int)entries.size(); indx++) | for (int indx = 0; indx < (int)entries.size(); indx++) |
{ | { |
// The Monitor should only look at entries in the table that are | // The Monitor should only look at entries in the table that are |
|
|
(FD_ISSET(entries[indx].socket, &fdread))) | (FD_ISSET(entries[indx].socket, &fdread))) |
{ | { |
MessageQueue *q = MessageQueue::lookup(entries[indx].queueId); | MessageQueue *q = MessageQueue::lookup(entries[indx].queueId); |
PEG_TRACE((TRC_HTTP, Tracer::LEVEL4, |
Tracer::trace(TRC_HTTP, Tracer::LEVEL4, |
"Monitor::run indx = %d, queueId = %d, q = %p", | "Monitor::run indx = %d, queueId = %d, q = %p", |
indx, entries[indx].queueId, q)); |
indx, entries[indx].queueId, q); |
PEGASUS_ASSERT(q !=0); | PEGASUS_ASSERT(q !=0); |
| |
try | try |
{ | { |
if (entries[indx]._type == Monitor::CONNECTION) | if (entries[indx]._type == Monitor::CONNECTION) |
{ | { |
PEG_TRACE((TRC_HTTP, Tracer::LEVEL4, |
Tracer::trace(TRC_HTTP, Tracer::LEVEL4, |
"entries[indx].type for indx = %d is " | "entries[indx].type for indx = %d is " |
"Monitor::CONNECTION", | "Monitor::CONNECTION", |
indx)); |
indx); |
|
static_cast<HTTPConnection *>(q)->_entry_index = indx; |
|
|
|
// Do not update the entry just yet. The entry gets |
|
// updated once the request has been read. |
|
//entries[indx]._status = _MonitorEntry::BUSY; |
|
|
|
// If allocate_and_awaken failure, retry on next |
|
// iteration |
|
/* Removed for PEP 183. |
|
if (!MessageQueueService::get_thread_pool()-> |
|
allocate_and_awaken((void *)q, _dispatch)) |
|
{ |
|
Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2, |
|
"Monitor::run: Insufficient resources to " |
|
"process request."); |
|
entries[indx]._status = _MonitorEntry::IDLE; |
|
return true; |
|
} |
|
*/ |
|
// Added for PEP 183 |
HTTPConnection *dst = | HTTPConnection *dst = |
reinterpret_cast<HTTPConnection *>(q); | reinterpret_cast<HTTPConnection *>(q); |
dst->_entry_index = indx; |
Tracer::trace(TRC_HTTP, Tracer::LEVEL4, |
|
|
// Update idle start time because we have received some |
|
// data. Any data is good data at this point, and we'll |
|
// keep the connection alive, even if we've exceeded |
|
// the idleConnectionTimeout, which will be checked |
|
// when we call closeConnectionOnTimeout() next. |
|
Time::gettimeofday(&dst->_idleStartTime); |
|
|
|
// Check for accept pending (ie. SSL handshake pending) |
|
// or idle connection timeouts for sockets from which |
|
// we received data (avoiding extra queue lookup below). |
|
if (!dst->closeConnectionOnTimeout(&timeNow)) |
|
{ |
|
PEG_TRACE((TRC_HTTP, Tracer::LEVEL4, |
|
"Monitor::_dispatch: entering run() for " | "Monitor::_dispatch: entering run() for " |
"indx = %d, queueId = %d, q = %p", | "indx = %d, queueId = %d, q = %p", |
dst->_entry_index, | dst->_entry_index, |
dst->_monitor-> |
dst->_monitor->_entries[dst->_entry_index].queueId, |
_entries[dst->_entry_index].queueId, |
dst); |
dst)); |
|
| |
try | try |
{ | { |
|
|
} | } |
catch (...) | catch (...) |
{ | { |
PEG_TRACE_CSTRING(TRC_HTTP, Tracer::LEVEL4, |
Tracer::trace(TRC_HTTP, Tracer::LEVEL4, |
"Monitor::_dispatch: exception received"); | "Monitor::_dispatch: exception received"); |
} | } |
PEG_TRACE((TRC_HTTP, Tracer::LEVEL4, |
Tracer::trace(TRC_HTTP, Tracer::LEVEL4, |
"Monitor::_dispatch: exited run() for index %d", | "Monitor::_dispatch: exited run() for index %d", |
dst->_entry_index)); |
dst->_entry_index); |
} |
|
|
// It is possible the entry status may not be set to |
|
// busy. The following will fail in that case. |
|
// PEGASUS_ASSERT(dst->_monitor->_entries[ |
|
// dst->_entry_index]._status.get() == |
|
// _MonitorEntry::BUSY); |
|
// Once the HTTPConnection thread has set the status |
|
// value to either Monitor::DYING or Monitor::IDLE, |
|
// it has returned control of the connection to the |
|
// Monitor. It is no longer permissible to access |
|
// the connection or the entry in the _entries table. |
|
|
|
// The following is not relevant as the worker thread |
|
// or the reader thread will update the status of the |
|
// entry. |
|
//if (dst->_connectionClosePending) |
|
//{ |
|
// dst->_monitor->_entries[dst->_entry_index]._status = |
|
// _MonitorEntry::DYING; |
|
//} |
|
//else |
|
//{ |
|
// dst->_monitor->_entries[dst->_entry_index]._status = |
|
// _MonitorEntry::IDLE; |
|
//} |
|
// end Added for PEP 183 |
} | } |
else if (entries[indx]._type == Monitor::INTERNAL) | else if (entries[indx]._type == Monitor::INTERNAL) |
{ | { |
|
|
if (amt == PEGASUS_SOCKET_ERROR && | if (amt == PEGASUS_SOCKET_ERROR && |
getSocketError() == PEGASUS_NETWORK_TCPIP_STOPPED) | getSocketError() == PEGASUS_NETWORK_TCPIP_STOPPED) |
{ | { |
PEG_TRACE_CSTRING(TRC_HTTP, Tracer::LEVEL4, |
Tracer::trace(TRC_HTTP, Tracer::LEVEL4, |
"Monitor::run: Tickler socket got an IO error. " | "Monitor::run: Tickler socket got an IO error. " |
"Going to re-create Socket and wait for " | "Going to re-create Socket and wait for " |
"TCP/IP restart."); | "TCP/IP restart."); |
|
|
} | } |
else | else |
{ | { |
PEG_TRACE((TRC_HTTP, Tracer::LEVEL4, |
Tracer::trace(TRC_HTTP, Tracer::LEVEL4, |
"Non-connection entry, indx = %d, has been " | "Non-connection entry, indx = %d, has been " |
"received.", | "received.", |
indx)); |
indx); |
int events = 0; | int events = 0; |
events |= SocketMessage::READ; | events |= SocketMessage::READ; |
Message* msg = new SocketMessage( | Message* msg = new SocketMessage( |
|
|
{ | { |
} | } |
} | } |
// else check for accept pending (ie. SSL handshake pending) or |
|
// idle connection timeouts for sockets from which we did not |
|
// receive data. |
|
else if ((entries[indx]._status.get() == _MonitorEntry::IDLE) && |
|
entries[indx]._type == Monitor::CONNECTION) |
|
{ |
|
MessageQueue *q = MessageQueue::lookup(entries[indx].queueId); |
|
HTTPConnection *dst = reinterpret_cast<HTTPConnection *>(q); |
|
dst->_entry_index = indx; |
|
dst->closeConnectionOnTimeout(&timeNow); |
|
} |
|
} |
|
} |
|
// else if "events" is zero (ie. select timed out) then we still need |
|
// to check if there are any pending SSL handshakes that have timed out. |
|
else |
|
{ |
|
for (int indx = 0; indx < (int)entries.size(); indx++) |
|
{ |
|
if ((entries[indx]._status.get() == _MonitorEntry::IDLE) && |
|
entries[indx]._type == Monitor::CONNECTION) |
|
{ |
|
MessageQueue *q = MessageQueue::lookup(entries[indx].queueId); |
|
HTTPConnection *dst = reinterpret_cast<HTTPConnection *>(q); |
|
dst->_entry_index = indx; |
|
dst->closeConnectionOnTimeout(&timeNow); |
|
} |
|
} | } |
} | } |
} | } |
|
|
ThreadReturnType PEGASUS_THREAD_CDECL Monitor::_dispatch(void* parm) | ThreadReturnType PEGASUS_THREAD_CDECL Monitor::_dispatch(void* parm) |
{ | { |
HTTPConnection *dst = reinterpret_cast<HTTPConnection *>(parm); | HTTPConnection *dst = reinterpret_cast<HTTPConnection *>(parm); |
PEG_TRACE((TRC_HTTP, Tracer::LEVEL4, |
Tracer::trace(TRC_HTTP, Tracer::LEVEL4, |
"Monitor::_dispatch: entering run() for indx = %d, queueId = %d, " | "Monitor::_dispatch: entering run() for indx = %d, queueId = %d, " |
"q = %p", | "q = %p", |
dst->_entry_index, | dst->_entry_index, |
dst->_monitor->_entries[dst->_entry_index].queueId, | dst->_monitor->_entries[dst->_entry_index].queueId, |
dst)); |
dst); |
| |
try | try |
{ | { |
|
|
} | } |
catch (...) | catch (...) |
{ | { |
PEG_TRACE_CSTRING(TRC_HTTP, Tracer::LEVEL4, |
Tracer::trace(TRC_HTTP, Tracer::LEVEL4, |
"Monitor::_dispatch: exception received"); | "Monitor::_dispatch: exception received"); |
} | } |
PEG_TRACE((TRC_HTTP, Tracer::LEVEL4, |
Tracer::trace(TRC_HTTP, Tracer::LEVEL4, |
"Monitor::_dispatch: exited run() for index %d", dst->_entry_index)); |
"Monitor::_dispatch: exited run() for index %d", dst->_entry_index); |
| |
PEGASUS_ASSERT(dst->_monitor->_entries[dst->_entry_index]._status.get() == | PEGASUS_ASSERT(dst->_monitor->_entries[dst->_entry_index]._status.get() == |
_MonitorEntry::BUSY); | _MonitorEntry::BUSY); |