version 1.114, 2006/09/13 20:57:39
|
version 1.115, 2006/10/04 11:20:36
|
|
|
| |
Monitor::~Monitor() | Monitor::~Monitor() |
{ | { |
|
uninitializeTickler(); |
|
Socket::uninitializeInterface(); |
|
Tracer::trace(TRC_HTTP, Tracer::LEVEL4, |
|
"returning from monitor destructor"); |
|
} |
|
void Monitor::uninitializeTickler(){ |
|
|
Tracer::trace(TRC_HTTP, Tracer::LEVEL4, "uninitializing interface"); | Tracer::trace(TRC_HTTP, Tracer::LEVEL4, "uninitializing interface"); |
| |
try{ | try{ |
|
|
"Failed to close tickle sockets"); | "Failed to close tickle sockets"); |
} | } |
| |
Socket::uninitializeInterface(); |
|
Tracer::trace(TRC_HTTP, Tracer::LEVEL4, |
|
"returning from monitor destructor"); |
|
} | } |
| |
void Monitor::initializeTickler(){ | void Monitor::initializeTickler(){ |
|
|
*/ | */ |
| |
/* setup the tickle server/listener */ | /* setup the tickle server/listener */ |
|
// try until the tcpip is restarted |
|
do |
|
{ |
| |
// get a socket for the server side | // get a socket for the server side |
if((_tickle_server_socket = ::socket(PF_INET, SOCK_STREAM, 0)) == PEGASUS_INVALID_SOCKET){ |
if((_tickle_server_socket = Socket::createSocket(PF_INET, SOCK_STREAM, 0)) == PEGASUS_INVALID_SOCKET) |
|
{ |
//handle error | //handle error |
MessageLoaderParms parms("Common.Monitor.TICKLE_CREATE", | MessageLoaderParms parms("Common.Monitor.TICKLE_CREATE", |
"Received error number $0 while creating the internal socket.", | "Received error number $0 while creating the internal socket.", |
|
|
throw Exception(parms); | throw Exception(parms); |
} | } |
| |
// set TCP_NODELAY |
|
int opt = 1; |
|
setsockopt(_tickle_server_socket, IPPROTO_TCP, TCP_NODELAY, (char*)&opt, sizeof(opt)); |
|
|
|
// initialize the address | // initialize the address |
memset(&_tickle_server_addr, 0, sizeof(_tickle_server_addr)); | memset(&_tickle_server_addr, 0, sizeof(_tickle_server_addr)); |
#ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM | #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM |
|
|
// bind server side to socket | // bind server side to socket |
if((::bind(_tickle_server_socket, | if((::bind(_tickle_server_socket, |
reinterpret_cast<struct sockaddr*>(&_tickle_server_addr), | reinterpret_cast<struct sockaddr*>(&_tickle_server_addr), |
sizeof(_tickle_server_addr))) < 0){ |
sizeof(_tickle_server_addr))) < 0) |
|
{ |
// handle error | // handle error |
#ifdef PEGASUS_OS_ZOS | #ifdef PEGASUS_OS_ZOS |
MessageLoaderParms parms("Common.Monitor.TICKLE_BIND_LONG", | MessageLoaderParms parms("Common.Monitor.TICKLE_BIND_LONG", |
"Received error:$0 while binding the internal socket.",strerror(errno)); |
"Received error:$0 while binding the internal socket." |
|
,strerror(errno)); |
#else | #else |
MessageLoaderParms parms("Common.Monitor.TICKLE_BIND", | MessageLoaderParms parms("Common.Monitor.TICKLE_BIND", |
"Received error number $0 while binding the internal socket.", | "Received error number $0 while binding the internal socket.", |
|
|
} | } |
| |
// tell the kernel we are a server | // tell the kernel we are a server |
if((::listen(_tickle_server_socket,3)) < 0){ |
if((::listen(_tickle_server_socket,3)) < 0) |
|
{ |
// handle error | // handle error |
MessageLoaderParms parms("Common.Monitor.TICKLE_LISTEN", | MessageLoaderParms parms("Common.Monitor.TICKLE_LISTEN", |
"Received error number $0 while listening to the internal socket.", | "Received error number $0 while listening to the internal socket.", |
|
|
int sock = ::getsockname(_tickle_server_socket, | int sock = ::getsockname(_tickle_server_socket, |
reinterpret_cast<struct sockaddr*>(&_tickle_server_addr), | reinterpret_cast<struct sockaddr*>(&_tickle_server_addr), |
&_addr_size); | &_addr_size); |
if(sock < 0){ |
if(sock < 0) |
|
{ |
// handle error | // handle error |
MessageLoaderParms parms("Common.Monitor.TICKLE_SOCKNAME", | MessageLoaderParms parms("Common.Monitor.TICKLE_SOCKNAME", |
"Received error number $0 while getting the internal socket name.", | "Received error number $0 while getting the internal socket name.", |
|
|
/* set up the tickle client/connector */ | /* set up the tickle client/connector */ |
| |
// get a socket for our tickle client | // get a socket for our tickle client |
if((_tickle_client_socket = ::socket(PF_INET, SOCK_STREAM, 0)) == PEGASUS_INVALID_SOCKET){ |
if((_tickle_client_socket = Socket::createSocket(PF_INET, SOCK_STREAM, 0)) |
|
== PEGASUS_INVALID_SOCKET) |
|
{ |
// handle error | // handle error |
MessageLoaderParms parms("Common.Monitor.TICKLE_CLIENT_CREATE", | MessageLoaderParms parms("Common.Monitor.TICKLE_CLIENT_CREATE", |
"Received error number $0 while creating the internal client socket.", | "Received error number $0 while creating the internal client socket.", |
|
|
throw Exception(parms); | throw Exception(parms); |
} | } |
| |
// set TCP_NODELAY |
|
setsockopt(_tickle_client_socket, IPPROTO_TCP, TCP_NODELAY, (char*)&opt, sizeof(opt)); |
|
|
|
// setup the address of the client | // setup the address of the client |
memset(&_tickle_client_addr, 0, sizeof(_tickle_client_addr)); | memset(&_tickle_client_addr, 0, sizeof(_tickle_client_addr)); |
#ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM | #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM |
|
|
// bind socket to client side | // bind socket to client side |
if((::bind(_tickle_client_socket, | if((::bind(_tickle_client_socket, |
reinterpret_cast<struct sockaddr*>(&_tickle_client_addr), | reinterpret_cast<struct sockaddr*>(&_tickle_client_addr), |
sizeof(_tickle_client_addr))) < 0){ |
sizeof(_tickle_client_addr))) < 0) |
|
{ |
// handle error | // handle error |
MessageLoaderParms parms("Common.Monitor.TICKLE_CLIENT_BIND", | MessageLoaderParms parms("Common.Monitor.TICKLE_CLIENT_BIND", |
"Received error number $0 while binding the internal client socket.", | "Received error number $0 while binding the internal client socket.", |
|
|
// connect to server side | // connect to server side |
if((::connect(_tickle_client_socket, | if((::connect(_tickle_client_socket, |
reinterpret_cast<struct sockaddr*>(&_tickle_server_addr), | reinterpret_cast<struct sockaddr*>(&_tickle_server_addr), |
sizeof(_tickle_server_addr))) < 0){ |
sizeof(_tickle_server_addr))) < 0) |
|
{ |
// handle error | // handle error |
MessageLoaderParms parms("Common.Monitor.TICKLE_CLIENT_CONNECT", | MessageLoaderParms parms("Common.Monitor.TICKLE_CLIENT_CONNECT", |
"Received error number $0 while connecting the internal client socket.", | "Received error number $0 while connecting the internal client socket.", |
|
|
// this call may fail, we will try a max of 20 times to establish this peer connection | // this call may fail, we will try a max of 20 times to establish this peer connection |
if((_tickle_peer_socket = ::accept(_tickle_server_socket, | if((_tickle_peer_socket = ::accept(_tickle_server_socket, |
reinterpret_cast<struct sockaddr*>(&_tickle_peer_addr), | reinterpret_cast<struct sockaddr*>(&_tickle_peer_addr), |
&peer_size)) < 0){ |
&peer_size)) < 0) |
#if !defined(PEGASUS_OS_TYPE_WINDOWS) |
{ |
// Only retry on non-windows platforms. |
if(_tickle_peer_socket == PEGASUS_SOCKET_ERROR |
if(_tickle_peer_socket == -1 && errno == EAGAIN) |
&& getSocketError() == PEGASUS_NETWORK_TRYAGAIN) |
{ | { |
int retries = 0; | int retries = 0; |
do | do |
|
|
reinterpret_cast<struct sockaddr*>(&_tickle_peer_addr), | reinterpret_cast<struct sockaddr*>(&_tickle_peer_addr), |
&peer_size); | &peer_size); |
retries++; | retries++; |
} while(_tickle_peer_socket == -1 && errno == EAGAIN && retries < 20); |
} while(_tickle_peer_socket == PEGASUS_SOCKET_ERROR |
|
&& getSocketError() == PEGASUS_NETWORK_TRYAGAIN |
|
&& retries < 20); |
|
} |
|
// TCP/IP is down, destroy sockets and retry again. |
|
if(_tickle_peer_socket == PEGASUS_SOCKET_ERROR && |
|
getSocketError() == PEGASUS_NETWORK_TCPIP_STOPPED ) |
|
{ |
|
// destroy everything |
|
uninitializeTickler(); |
|
// retry again. |
|
continue; |
} | } |
#endif |
|
} | } |
if(_tickle_peer_socket == -1){ |
if(_tickle_peer_socket == PEGASUS_SOCKET_ERROR) |
|
{ |
// handle error | // handle error |
MessageLoaderParms parms("Common.Monitor.TICKLE_ACCEPT", | MessageLoaderParms parms("Common.Monitor.TICKLE_ACCEPT", |
"Received error number $0 while accepting the internal socket connection.", | "Received error number $0 while accepting the internal socket connection.", |
getSocketError()); | getSocketError()); |
throw Exception(parms); | throw Exception(parms); |
|
} else |
|
{ |
|
// socket is ok |
|
break; |
} | } |
|
} while(1); // try until TCP/IP is restarted |
| |
Socket::disableBlocking(_tickle_peer_socket); | Socket::disableBlocking(_tickle_peer_socket); |
Socket::disableBlocking(_tickle_client_socket); | Socket::disableBlocking(_tickle_client_socket); |
|
|
// checks entries with IDLE state for events | // checks entries with IDLE state for events |
_MonitorEntry entry(_tickle_peer_socket, 1, INTERNAL); | _MonitorEntry entry(_tickle_peer_socket, 1, INTERNAL); |
entry._status = _MonitorEntry::IDLE; | entry._status = _MonitorEntry::IDLE; |
|
|
|
// is the tickler initalized as first socket on startup ? |
|
if (_entries.size()==0) |
|
{ |
|
// if yes, append a new entry |
_entries.append(entry); | _entries.append(entry); |
} | } |
|
else |
|
{ |
|
// if not, overwrite the tickler entry with new socket |
|
_entries[0]=entry; |
|
} |
|
|
|
} |
| |
void Monitor::tickle(void) | void Monitor::tickle(void) |
{ | { |
|
|
entries[indx]._status = _MonitorEntry::BUSY; | entries[indx]._status = _MonitorEntry::BUSY; |
static char buffer[2]; | static char buffer[2]; |
Sint32 amt = Socket::read(entries[indx].socket,&buffer, 2); | Sint32 amt = Socket::read(entries[indx].socket,&buffer, 2); |
|
|
|
if(amt == PEGASUS_SOCKET_ERROR && |
|
getSocketError() == PEGASUS_NETWORK_TCPIP_STOPPED ) |
|
{ |
|
Tracer::trace(TRC_HTTP, Tracer::LEVEL4, |
|
"Monitor::run: Tickler socket got an IO error. " |
|
"Going to re-create Socket and wait for TCP/IP restart."); |
|
uninitializeTickler(); |
|
initializeTickler(); |
|
|
|
} else |
|
{ |
entries[indx]._status = _MonitorEntry::IDLE; | entries[indx]._status = _MonitorEntry::IDLE; |
} | } |
|
|
|
} |
else | else |
{ | { |
Tracer::trace(TRC_HTTP, Tracer::LEVEL4, | Tracer::trace(TRC_HTTP, Tracer::LEVEL4, |