Module: nagvis Branch: master Commit: ce41cfbd025a5c46c6b09a1fb33a7fe7b3aca38b URL: http://nagvis.git.sourceforge.net/git/gitweb.cgi?p=nagvis/nagvis;a=commit;h=ce41cfbd025a5c46c6b09a1fb33a7fe7b3aca38b
Author: LaMi <[email protected]> Date: Mon Nov 16 09:38:25 2009 +0100 The backend uses a persistent connection for each NagVis call. No need to open a new connection to the socket for each livestatus query anymore --- .../core/classes/GlobalBackendmklivestatus.php | 108 +++++++++++++++----- 1 files changed, 82 insertions(+), 26 deletions(-) diff --git a/share/server/core/classes/GlobalBackendmklivestatus.php b/share/server/core/classes/GlobalBackendmklivestatus.php index 4d867a7..20c8a21 100644 --- a/share/server/core/classes/GlobalBackendmklivestatus.php +++ b/share/server/core/classes/GlobalBackendmklivestatus.php @@ -37,6 +37,7 @@ class GlobalBackendmklivestatus implements GlobalBackendInterface { private $backendId = ''; + private $SOCKET = null; private $socketType = ''; private $socketPath = ''; private $socketAddress = ''; @@ -131,66 +132,100 @@ class GlobalBackendmklivestatus implements GlobalBackendInterface { return false; } } - + /** - * PRIVATE queryLivestatus() + * PRIVATE connectSocket() * - * Queries the livestatus socket and returns the result as array + * Connects to the livestatus socket when no connection is open * - * @param String Query to send to the socket - * @return Array Results of the query - * @author Mathias Kettner <[email protected]> * @author Lars Michelsen <[email protected]> */ - private function queryLivestatus($query) { - $sock = false; - + private function connectSocket() { // Create socket connection if($this->socketType === 'unix') { - $sock = socket_create(AF_UNIX, SOCK_STREAM, 0); + $this->SOCKET = socket_create(AF_UNIX, SOCK_STREAM, 0); } elseif($this->socketType === 'tcp') { - $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); + $this->SOCKET = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); } - if($sock == false) { + if($this->SOCKET == false) { new GlobalMessage('ERROR', GlobalCore::getInstance()->getLang()->getText('Could not create livestatus socket [SOCKET] in backend [BACKENDID].', Array('BACKENDID' => $this->backendId, 'SOCKET' => $this->socketPath))); return Array(); } // Connect to the socket if($this->socketType === 'unix') { - $result = socket_connect($sock, $this->socketPath); + $result = socket_connect($this->SOCKET, $this->socketPath); } elseif($this->socketType === 'tcp') { - $result = socket_connect($sock, $this->socketAddress, $this->socketPort); + $result = socket_connect($this->SOCKET, $this->socketAddress, $this->socketPort); } if($result == false) { - new GlobalMessage('ERROR', GlobalCore::getInstance()->getLang()->getText('Unable to connect to the [SOCKET] in backend [BACKENDID]: [MSG]', Array('BACKENDID' => $this->backendId, 'SOCKET' => $this->socketPath, 'MSG' => socket_strerror(socket_last_error($sock))))); + new GlobalMessage('ERROR', GlobalCore::getInstance()->getLang()->getText('Unable to connect to the [SOCKET] in backend [BACKENDID]: [MSG]', Array('BACKENDID' => $this->backendId, 'SOCKET' => $this->socketPath, 'MSG' => socket_strerror(socket_last_error($this->SOCKET))))); return Array(); } + } + + /** + * PRIVATE queryLivestatus() + * + * Queries the livestatus socket and returns the result as array + * + * @param String Query to send to the socket + * @return Array Results of the query + * @author Mathias Kettner <[email protected]> + * @author Lars Michelsen <[email protected]> + */ + private function queryLivestatus($query) { + // Only connect when no connection opened yet + if($this->SOCKET === null) { + $this->connectSocket(); + } // Query to get a json formated array back - socket_write($sock, $query . "OutputFormat:json\n"); - socket_shutdown($sock, 1); + // Use KeepAlive with fixed16 header + socket_write($this->SOCKET, $query . "OutputFormat:json\nKeepAlive: on\nResponseHeader: fixed16\n\n"); + + // Read 16 bytes to get the status code and body size + $read = $this->readSocket(16); + + // Catch problem while reading + if($read === false) { + new GlobalMessage('ERROR', GlobalCore::getInstance()->getLang()->getText('Problem while reading from socket [SOCKET] in backend [BACKENDID]: [MSG]', Array('BACKENDID' => $this->backendId, 'SOCKET' => $this->socketPath, 'MSG' => socket_strerror(socket_last_error($this->SOCKET))))); + } + + // Extract status code + $status = substr($read, 0, 3); - // Read all information from the response and add it to a string - $read = ''; - while('' != ($r = @socket_read($sock, 65536))) { - $read .= $r; + // Extract content length + $len = intval(trim(substr($read, 4, 11))); + + // Read socket until end of data + $read = $this->readSocket($len); + + // Catch problem while reading + if($read === false) { + new GlobalMessage('ERROR', GlobalCore::getInstance()->getLang()->getText('Problem while reading from socket [SOCKET] in backend [BACKENDID]: [MSG]', Array('BACKENDID' => $this->backendId, 'SOCKET' => $this->socketPath, 'MSG' => socket_strerror(socket_last_error($this->SOCKET))))); + } + + // Catch errors (Like HTTP 200 is OK) + if($status != "200") { + new GlobalMessage('ERROR', GlobalCore::getInstance()->getLang()->getText('Problem while reading from socket [SOCKET] in backend [BACKENDID]: [MSG]', Array('BACKENDID' => $this->backendId, 'SOCKET' => $this->socketPath, 'MSG' => $read))); } // Catch problems occured while reading? 104: Connection reset by peer - if(socket_last_error($sock) == 104) { - new GlobalMessage('ERROR', GlobalCore::getInstance()->getLang()->getText('Problem while reading from socket [SOCKET] in backend [BACKENDID]: [MSG]', Array('BACKENDID' => $this->backendId, 'SOCKET' => $this->socketPath, 'MSG' => socket_strerror(socket_last_error($sock))))); + if(socket_last_error($this->SOCKET) == 104) { + new GlobalMessage('ERROR', GlobalCore::getInstance()->getLang()->getText('Problem while reading from socket [SOCKET] in backend [BACKENDID]: [MSG]', Array('BACKENDID' => $this->backendId, 'SOCKET' => $this->socketPath, 'MSG' => socket_strerror(socket_last_error($this->SOCKET))))); return Array(); } - // Important: The socket needs to be closed after reading - socket_close($sock); - // Decode the json response $obj = json_decode($read); + // TEST: Disable KeepAlive: + //socket_close($this->SOCKET); + //$this->SOCKET = null; + // json_decode returns null on syntax problems if($obj === null) { new GlobalMessage('ERROR', GlobalCore::getInstance()->getLang()->getText('The response has an invalid format in backend [BACKENDID].', Array('BACKENDID' => $this->backendId))); @@ -200,6 +235,27 @@ class GlobalBackendmklivestatus implements GlobalBackendInterface { return $obj; } } + + public function readSocket($len) { + $offset = 0; + $socketData = ''; + + while($offset < $len) { + if(($data = @socket_read($this->SOCKET, $len-$offset)) === false) { + return false; + } + + $dataLen = strlen ($data); + $offset += $dataLen; + $socketData .= $data; + + if($dataLen == 0) { + break; + } + } + + return $socketData; + } /** * PRIVATE queryLivestatusSingle() ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july _______________________________________________ Nagvis-checkins mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/nagvis-checkins
