Livestatus\Connection: switch to new fetch methods

This commit is contained in:
Thomas Gelf 2014-11-16 16:25:47 +01:00
parent efd395e12a
commit fd55ffe47e

View File

@ -32,6 +32,13 @@ class Connection
const TYPE_UNIX = 1; const TYPE_UNIX = 1;
const TYPE_TCP = 2; const TYPE_TCP = 2;
protected $bytesRead = 0;
protected $responseSize;
protected $status;
protected $headers;
// List of available Livestatus tables. Kept here as we otherwise get no
// useful error message
protected $available_tables = array( protected $available_tables = array(
'hosts', // hosts 'hosts', // hosts
'services', // services, joined with all data from hosts 'services', // services, joined with all data from hosts
@ -110,9 +117,10 @@ class Connection
{ {
return 100; return 100;
$count = clone($query); $count = clone($query);
$count->count(); // WTF? $count->count();
Benchmark::measure('Sending Livestatus Count Query'); Benchmark::measure('Sending Livestatus Count Query');
$data = $this->doFetch((string) $count); $this->execute($query);
$data = $this->fetchRowFromSocket();
Benchmark::measure('Got Livestatus count result'); Benchmark::measure('Got Livestatus count result');
return $data[0][0]; return $data[0][0];
} }
@ -163,21 +171,26 @@ class Connection
public function fetchAll(Query $query) public function fetchAll(Query $query)
{ {
Benchmark::measure('Sending Livestatus Query'); Benchmark::measure('Sending Livestatus Query');
$data = $this->doFetch((string) $query); $this->execute($query);
Benchmark::measure('Got Livestatus Data'); Benchmark::measure('Got Livestatus Data');
if ($query->hasColumns()) { if ($query->hasColumns()) {
$headers = $query->getColumnAliases(); $headers = $query->getColumnAliases();
} else { } else {
// TODO: left this here, find out how to handle it better
die('F*** no data');
$headers = array_shift($data); $headers = array_shift($data);
} }
$result = array(); $result = array();
foreach ($data as $row) { $filter = $query->filterIsSupported() ? null : $query->getFilter();
$result_row = & $result[];
$result_row = (object) array(); while ($row = $this->fetchRowFromSocket()) {
foreach ($row as $key => $val) { $r = new ResponseRow($row, $query);
$result_row->{$headers[$key]} = $val; $res = $query->resultRow($row);
} if ($filter !== null && ! $filter->matches($res)) continue;
$result[] = $res;
} }
if ($query->hasOrder()) { if ($query->hasOrder()) {
usort($result, array($query, 'compare')); usort($result, array($query, 'compare'));
} }
@ -193,59 +206,49 @@ class Connection
return $result; return $result;
} }
protected function doFetch($raw_query) protected function hasBeenExecuted()
{ {
$conn = $this->getConnection(); return $this->status !== null;
$this->writeToSocket($raw_query);
$header = $this->readFromSocket(16);
$status = (int) substr($header, 0, 3);
$length = (int) trim(substr($header, 4));
$body = $this->readFromSocket($length);
if ($status !== 200) {
throw new IcingaException(
'Problem while reading %d bytes from livestatus: %s',
$length,
$body
);
}
$result = json_decode($body);
if ($result === null) {
throw new IcingaException('Got invalid response body from livestatus');
} }
return $result; protected function execute($query)
}
protected function readFromSocket($length)
{ {
$offset = 0; // Reset state
$buffer = ''; $this->status = null;
$this->responseSize = null;
$this->bytesRead = 0;
while ($offset < $length) { $raw = $query->toString();
$data = socket_read($this->connection, $length - $offset);
if ($data === false) { Benchmark::measure($raw);
throw new IcingaException(
'Failed to read from livestatus socket: %s', // "debug"
socket_strerror(socket_last_error($this->connection)) // echo $raw . "\n<br>";
$this->writeToSocket($raw);
$header = $this->readLineFromSocket();
if (! preg_match('~^(\d{3})\s\s*(\d+)$~', $header, $m)) {
$this->disconnect();
throw new Exception(
sprintf('Got invalid header. First 16 Bytes: %s', $header)
); );
} }
$size = strlen($data); $this->status = (int) $m[1];
$offset += $size; $this->bytesRead = 0;
$buffer .= $data; $this->responseSize = (int) $m[2];
if ($this->status !== 200) {
if ($size === 0) { // "debug"
break; //die(var_export($raw, 1));
} throw new Exception(
} sprintf(
if ($offset !== $length) { 'Error %d while querying livestatus: %s %s',
throw new IcingaException( $this->status,
'Got only %d instead of %d bytes from livestatus socket', $raw,
$offset, $this->readLineFromSocket()
$length )
); );
} }
$this->discoverColumnHeaders($query);
return $buffer;
} }
protected function discoverColumnHeaders($query) protected function discoverColumnHeaders($query)