diff --git a/database/yggstate.mwb b/database/yggstate.mwb index 330f18f..941019f 100644 Binary files a/database/yggstate.mwb and b/database/yggstate.mwb differ diff --git a/media/db-prototype.png b/media/db-prototype.png index f729fd1..9a09e5d 100644 Binary files a/media/db-prototype.png and b/media/db-prototype.png differ diff --git a/src/crontab/crawler.php b/src/crontab/crawler.php index b61256b..632092b 100644 --- a/src/crontab/crawler.php +++ b/src/crontab/crawler.php @@ -39,12 +39,32 @@ $debug = [ 'online' => 0, 'insert' => 0, ], - 'remote' => [ + 'session' => [ 'total' => [ 'insert' => 0, 'update' => 0, ] ], + 'remote' => [ + 'total' => [ + 'insert' => 0, + ], + 'scheme' => [ + 'total' => [ + 'insert' => 0, + ] + ], + 'host' => [ + 'total' => [ + 'insert' => 0, + ] + ], + 'port' => [ + 'total' => [ + 'insert' => 0, + ] + ] + ], 'coordinate' => [ 'total' => [ 'insert' => 0, @@ -52,10 +72,14 @@ $debug = [ 'route' => [ 'total' => [ 'insert' => 0, - 'delete' => 0, ] ] ], + 'connection' => [ + 'total' => [ + 'insert' => 0, + ], + ], ] ] ]; @@ -73,7 +97,7 @@ try { } // Collect connected peers -if ($connectedPeers = Yggverse\Yggdrasilctl\Yggdrasil::getPeers()) { +if ($connectedPeers = \Yggverse\Yggdrasilctl\Yggdrasil::getPeers()) { foreach ($connectedPeers as $connectedPeerAddress => $connectedPeerInfo) { @@ -94,97 +118,165 @@ if ($connectedPeers = Yggverse\Yggdrasilctl\Yggdrasil::getPeers()) { } } - // Init peer remote - if ($connectedPeerRemoteUrl = Yggverse\Parser\Url::parse($connectedPeerInfo->remote)) { + // Init peer session + if ($dbLastPeerSession = $db->findLastPeerSessionByPeerId($dbPeerId)) { - if ($dbPeerRemote = $db->findPeerRemote($dbPeerId, - $connectedPeerRemoteUrl->host->scheme, - $connectedPeerRemoteUrl->host->name, - $connectedPeerRemoteUrl->host->port)) { + $dbPeerSessionId = $dbLastPeerSession->peerSessionId; - // Update connection stats - if ($dbPeerRemote->received < $connectedPeerInfo->bytes_recvd) { + // If remote session uptime < than stored, register new one + if ($connectedPeerInfo->uptime < $dbLastPeerSession->uptime) { - $debug['yggdrasil']['peer']['remote']['total']['update'] += - $db->updatePeerRemoteReceived($dbPeerRemote->peerRemoteId, $connectedPeerInfo->bytes_recvd, time()); + if ($dbPeerSessionId = $db->addPeerSession($dbPeerId, + round($connectedPeerInfo->uptime), + $connectedPeerInfo->bytes_sent, + $connectedPeerInfo->bytes_recvd, + time())) { + + $debug['yggdrasil']['peer']['session']['total']['insert']++; } - if ($dbPeerRemote->sent < $connectedPeerInfo->bytes_sent) { + } else { - $debug['yggdrasil']['peer']['remote']['total']['update'] += - $db->updatePeerRemoteSent($dbPeerRemote->peerRemoteId, $connectedPeerInfo->bytes_sent, time()); - } + $debug['yggdrasil']['peer']['session']['total']['update'] += + $db->updatePeerSession($dbLastPeerSession->peerSessionId, + round($connectedPeerInfo->uptime), + $connectedPeerInfo->bytes_sent, + $connectedPeerInfo->bytes_recvd, + time()); + } - if ($dbPeerRemote->uptime < $connectedPeerInfo->uptime) { + } else { - $debug['yggdrasil']['peer']['remote']['total']['update'] += - $db->updatePeerRemoteUptime($dbPeerRemote->peerRemoteId, $connectedPeerInfo->uptime, time()); + if ($dbPeerSessionId = $db->addPeerSession($dbPeerId, + round($connectedPeerInfo->uptime), + $connectedPeerInfo->bytes_sent, + $connectedPeerInfo->bytes_recvd, + time())) { + + $debug['yggdrasil']['peer']['session']['total']['insert']++; + } + } + + // Init peer coordinate + if ($dbPeerCoordinate = $db->findLastPeerCoordinateByPeerId($dbPeerId)) { + + $dbPeerCoordinateId = $dbPeerCoordinate->peerCoordinateId; + + // Peer have changed it port, init new coordinate + if ($dbPeerCoordinate->port != $connectedPeerInfo->port) { + + if ($dbPeerCoordinateId = $db->addPeerCoordinate($dbPeerId, $connectedPeerInfo->port, time())) { + + $debug['yggdrasil']['peer']['coordinate']['total']['insert']++; } + } - $debug['yggdrasil']['peer']['remote']['total']['update'] += - $db->updatePeerRemoteTimeOnline($dbPeerRemote->peerRemoteId, time()); + } else { - } else { + if ($dbPeerCoordinateId = $db->addPeerCoordinate($dbPeerId, $connectedPeerInfo->port, time())) { + + $debug['yggdrasil']['peer']['coordinate']['total']['insert']++; + } + } - if ($peerRemoteId = $db->addPeerRemote($dbPeerId, - $connectedPeerRemoteUrl->host->scheme, - $connectedPeerRemoteUrl->host->name, - $connectedPeerRemoteUrl->host->port, - $connectedPeerInfo->bytes_recvd, - $connectedPeerInfo->bytes_sent, - $connectedPeerInfo->uptime, - time())) { + // Init peer coordinate route + $dbCoords = []; + foreach ($db->findPeerCoordinateRouteByCoordinateId($dbPeerCoordinateId) as $dbPeerCoordinateRoute) { + $dbCoords[$dbPeerCoordinateRoute->level] = $dbPeerCoordinateRoute->port; + } - $debug['yggdrasil']['peer']['remote']['total']['insert']++; + // Compare remote / local route, create new on changed + if ($dbCoords !== $connectedPeerInfo->coords) { - $debug['yggdrasil']['peer']['remote']['total']['update'] += - $db->updatePeerRemoteTimeOnline($peerRemoteId, time()); + if ($dbPeerCoordinateId = $db->addPeerCoordinate($dbPeerId, $connectedPeerInfo->port, time())) { + + $debug['yggdrasil']['peer']['coordinate']['total']['insert']++; + } + + foreach ($connectedPeerInfo->coords as $level => $port) { + + if ($db->addPeerCoordinateRoute($dbPeerCoordinateId, $level, $port)) { + + $debug['yggdrasil']['peer']['coordinate']['route']['total']['insert']++; } } + } - // Init peer coordinate - if ($dbPeerCoordinate = $db->getLastCoordinate($dbPeerId)) { + // Init peer remote + if ($connectedPeerRemoteUrl = \Yggverse\Parser\Url::parse($connectedPeerInfo->remote)) { - $peerCoordinateId = $dbPeerCoordinate->peerCoordinateId; + // Init peer scheme + if ($dbPeerRemoteScheme = $db->findPeerRemoteScheme($connectedPeerRemoteUrl->host->scheme)) { - // Create new peer coordinate on port change - if ($dbPeerCoordinate->port !== $connectedPeerInfo->port) { + $dbPeerRemoteSchemeId = $dbPeerRemoteScheme->peerRemoteSchemeId; - if ($peerCoordinateId = $db->addPeerCoordinate($dbPeerId, $connectedPeerInfo->port, time())) { + } else { + + if ($dbPeerRemoteSchemeId = $db->addPeerRemoteScheme($connectedPeerRemoteUrl->host->scheme, time())) { - $debug['yggdrasil']['peer']['coordinate']['total']['insert']++; - } + $debug['yggdrasil']['peer']['remote']['scheme']['total']['insert']++; } + } + + // Init peer host + if ($dbPeerRemoteHost = $db->findPeerRemoteHost($connectedPeerRemoteUrl->host->name)) { + + $dbPeerRemoteHostId = $dbPeerRemoteHost->peerRemoteHostId; } else { - if ($peerCoordinateId = $db->addPeerCoordinate($dbPeerId, $connectedPeerInfo->port, time())) { + if ($dbPeerRemoteHostId = $db->addPeerRemoteHost($connectedPeerRemoteUrl->host->name, time())) { - $debug['yggdrasil']['peer']['coordinate']['total']['insert']++; + $debug['yggdrasil']['peer']['remote']['host']['total']['insert']++; } } - // Init peer coordinate routing - $localPeerCoordinateRoute = []; - foreach ($db->getPeerCoordinateRoute($peerCoordinateId) as $dbPeerCoordinateRoute) { + // Init peer port + if ($dbPeerRemotePort = $db->findPeerRemotePort($connectedPeerRemoteUrl->host->port)) { + + $dbPeerRemotePortId = $dbPeerRemotePort->peerRemotePortId; + + } else { + + if ($dbPeerRemotePortId = $db->addPeerRemotePort($connectedPeerRemoteUrl->host->port, time())) { - $localPeerCoordinateRoute[$dbPeerCoordinateRoute->level] = $dbPeerCoordinateRoute->port; + $debug['yggdrasil']['peer']['remote']['port']['total']['insert']++; + } } - // Compare remote and local routes to prevent extra writing operations - if ($localPeerCoordinateRoute !== $connectedPeerInfo->coords) { - $debug['yggdrasil']['peer']['coordinate']['route']['total']['delete'] += - $db->flushPeerCoordinateRoute($peerCoordinateId); + if ($dbPeerRemote = $db->findPeerRemote($dbPeerId, + $dbPeerRemoteSchemeId, + $dbPeerRemoteHostId, + $dbPeerRemotePortId)) { - foreach ($connectedPeerInfo->coords as $level => $port) { + $dbPeerRemoteId = $dbPeerRemote->peerRemoteId; + + } else { - if ($db->addPeerCoordinateRoute($peerCoordinateId, $level, $port)) { + if ($dbPeerRemoteId = $db->addPeerRemote($dbPeerId, + $dbPeerRemoteSchemeId, + $dbPeerRemoteHostId, + $dbPeerRemotePortId, + time())) { - $debug['yggdrasil']['peer']['coordinate']['route']['total']['insert']++; - } + $debug['yggdrasil']['peer']['remote']['total']['insert']++; } } + + // If something went wrong with URL parse, skip next operations for this peer + } else { + + continue; + } + + // Init peer connection + if (!$db->findPeerConnection($dbPeerSessionId, $dbPeerRemoteId, $dbPeerCoordinateId)) { + + if ($db->addPeerConnection($dbPeerSessionId, $dbPeerRemoteId, $dbPeerCoordinateId, time())) { + + $debug['yggdrasil']['peer']['connection']['total']['insert']++; + } } $debug['yggdrasil']['peer']['total']['online']++; diff --git a/src/library/mysql.php b/src/library/mysql.php index 4049ba8..204ce33 100644 --- a/src/library/mysql.php +++ b/src/library/mysql.php @@ -81,6 +81,28 @@ class MySQL { return $query->fetch(); } + public function getPeersTotal() : int { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT COUNT(*) AS `result` FROM `peer`'); + + $query->execute(); + + return $query->fetch()->result; + } + + public function getPeer(int $peerId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `peer` WHERE `peerId` = ? LIMIT 1'); + + $query->execute([$peerId]); + + return $query->fetch(); + } + public function getPeers() { $this->_debug->query->select->total++; @@ -93,76 +115,183 @@ class MySQL { } // Peer remote - public function addPeerRemote(int $peerId, string $scheme, string $host, int $port, int $received, int $sent, float $uptime, int $timeAdded) { + public function addPeerRemote(int $peerId, int $peerRemoteSchemeId, int $peerRemoteHostId, int $peerRemotePortId, int $timeAdded) { $this->_debug->query->insert->total++; - $query = $this->_db->prepare('INSERT INTO `peerRemote` SET `peerId` = ?, - `scheme` = ?, - `host` = ?, - `port` = ?, - `received` = ?, - `sent` = ?, + $query = $this->_db->prepare('INSERT INTO `peerRemote` SET `peerId` = ?, + `peerRemoteSchemeId` = ?, + `peerRemoteHostId` = ?, + `peerRemotePortId` = ?, + `timeAdded` = ?'); + + $query->execute([$peerId, $peerRemoteSchemeId, $peerRemoteHostId, $peerRemotePortId, $timeAdded]); + + return $this->_db->lastInsertId(); + } + + public function findPeerRemote(int $peerId, int $peerRemoteSchemeId, int $peerRemoteHostId, int $peerRemotePortId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `peerRemote` WHERE `peerId` = ? AND `peerRemoteSchemeId` = ? AND `peerRemoteHostId` = ? AND `peerRemotePortId` = ? LIMIT 1'); + + $query->execute([$peerId, $peerRemoteSchemeId, $peerRemoteHostId, $peerRemotePortId]); + + return $query->fetch(); + } + + public function findPeerRemoteScheme(string $name) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `peerRemoteScheme` WHERE `name` = ? LIMIT 1'); + + $query->execute([$name]); + + return $query->fetch(); + } + + public function addPeerRemoteScheme(string $name, int $timeAdded) { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `peerRemoteScheme` SET `name` = ?, `timeAdded` = ?'); + + $query->execute([$name, $timeAdded]); + + return $this->_db->lastInsertId(); + } + + public function findPeerRemoteHost(string $name) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `peerRemoteHost` WHERE `name` = ? LIMIT 1'); + + $query->execute([$name]); + + return $query->fetch(); + } + + public function addPeerRemoteHost(string $name, int $timeAdded) { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `peerRemoteHost` SET `name` = ?, `timeAdded` = ?'); + + $query->execute([$name, $timeAdded]); + + return $this->_db->lastInsertId(); + } + + public function findPeerRemotePort(mixed $name) { // int|null + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `peerRemotePort` WHERE `name` = ? LIMIT 1'); + + $query->execute([$name]); + + return $query->fetch(); + } + + public function addPeerRemotePort(mixed $name, int $timeAdded) { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `peerRemotePort` SET `name` = ?, `timeAdded` = ?'); + + $query->execute([$name, $timeAdded]); + + return $this->_db->lastInsertId(); + } + + // Peer session + public function addPeerSession(int $peerId, int $uptime, int $sent, int $received, int $timeAdded) { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `peerSession` SET `peerId` = ?, `uptime` = ?, + `sent` = ?, + `received` = ?, `timeAdded` = ?, `timeUpdated` = ?'); - $query->execute([$peerId, $scheme, $host, $port, $received, $sent, $uptime, $timeAdded, $timeAdded]); + $query->execute([$peerId, $uptime, $sent, $received, $timeAdded, $timeAdded]); return $this->_db->lastInsertId(); } - public function updatePeerRemoteReceived(int $peerRemoteId, int $received, int $timeUpdated) { + public function updatePeerSession(int $peerSessionId, int $uptime, int $sent, int $received, int $timeUpdated) { $this->_debug->query->update->total++; - $query = $this->_db->prepare('UPDATE `peerRemote` SET `received` = ?, `timeUpdated` = ? WHERE `peerRemoteId` = ? LIMIT 1'); + $query = $this->_db->prepare('UPDATE `peerSession` SET `uptime` = ?, `sent` = ?, `received` = ?, `timeUpdated` = ? WHERE `peerSessionId` = ? LIMIT 1'); - $query->execute([$received, $timeUpdated, $peerRemoteId]); + $query->execute([$uptime, $sent, $received, $timeUpdated, $peerSessionId]); return $query->rowCount(); } - public function updatePeerRemoteSent(int $peerRemoteId, int $sent, int $timeUpdated) { + public function findLastPeerSessionByPeerId(int $peerId) { - $this->_debug->query->update->total++; + $this->_debug->query->select->total++; - $query = $this->_db->prepare('UPDATE `peerRemote` SET `sent` = ?, `timeUpdated` = ? WHERE `peerRemoteId` = ? LIMIT 1'); + $query = $this->_db->prepare('SELECT * FROM `peerSession` WHERE `peerId` = ? ORDER BY `peerSessionId` DESC LIMIT 1'); - $query->execute([$sent, $timeUpdated, $peerRemoteId]); + $query->execute([$peerId]); - return $query->rowCount(); + return $query->fetch(); } - public function updatePeerRemoteUptime(int $peerRemoteId, float $uptime, int $timeUpdated) { + public function getPeerSessionSentSum() { - $this->_debug->query->update->total++; + $this->_debug->query->select->total++; - $query = $this->_db->prepare('UPDATE `peerRemote` SET `uptime` = ?, `timeUpdated` = ? WHERE `peerRemoteId` = ? LIMIT 1'); + $query = $this->_db->prepare('SELECT SUM(`sent`) AS `result` FROM `peerSession`'); - $query->execute([$uptime, $timeUpdated, $peerRemoteId]); + $query->execute(); - return $query->rowCount(); + return $query->fetch()->result; } - public function updatePeerRemoteTimeOnline(int $peerRemoteId, $time) { + public function getPeerSessionReceivedSum() { - $this->_debug->query->update->total++; + $this->_debug->query->select->total++; - $query = $this->_db->prepare('UPDATE `peerRemote` SET `timeOnline` = ?, `timeUpdated` = ? WHERE `peerRemoteId` = ? LIMIT 1'); + $query = $this->_db->prepare('SELECT SUM(`received`) AS `result` FROM `peerSession`'); - $query->execute([$time, $time, $peerRemoteId]); + $query->execute(); - return $query->rowCount(); + return $query->fetch()->result; + } + + // Peer connection + public function addPeerConnection(int $peerSessionId, int $peerRemoteId, int $peerCoordinateId, int $timeAdded) { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `peerConnection` SET `peerSessionId` = ?, + `peerRemoteId` = ?, + `peerCoordinateId` = ?, + `timeAdded` = ?'); + + $query->execute([$peerSessionId, $peerRemoteId, $peerCoordinateId, $timeAdded]); + + return $this->_db->lastInsertId(); } - public function findPeerRemote(int $peerId, string $scheme, string $host, int $port) { + public function findPeerConnection(int $peerSessionId, int $peerRemoteId, int $peerCoordinateId) { $this->_debug->query->select->total++; - $query = $this->_db->prepare('SELECT * FROM `peerRemote` WHERE `peerId` = ? AND `scheme` = ? AND `host` = ? AND `port` = ? LIMIT 1'); + $query = $this->_db->prepare('SELECT * FROM `peerConnection` + WHERE `peerSessionId` = ? AND `peerRemoteId` = ? AND `peerCoordinateId` = ? + LIMIT 1'); - $query->execute([$peerId, $scheme, $host, $port]); + $query->execute([$peerSessionId, $peerRemoteId, $peerCoordinateId]); return $query->fetch(); } @@ -196,29 +325,18 @@ class MySQL { return $this->_db->lastInsertId(); } - public function flushPeerCoordinateRoute(int $peerCoordinateId) { - - $this->_debug->query->delete->total++; - - $query = $this->_db->prepare('DELETE FROM `peerCoordinateRoute` WHERE `peerCoordinateId` = ?'); - - $query->execute([$peerCoordinateId]); - - return $query->rowCount(); - } - - public function getLastCoordinate(int $peerId) { + public function findLastPeerCoordinateByPeerId(int $peerId) { $this->_debug->query->select->total++; - $query = $this->_db->prepare('SELECT * FROM `peerCoordinate` WHERE `peerId` = ? ORDER BY `timeAdded` DESC LIMIT 1'); + $query = $this->_db->prepare('SELECT * FROM `peerCoordinate` WHERE `peerId` = ? ORDER BY `peerCoordinateId` DESC LIMIT 1'); $query->execute([$peerId]); return $query->fetch(); } - public function getPeerCoordinateRoute(int $peerCoordinateId) { + public function findPeerCoordinateRouteByCoordinateId(int $peerCoordinateId) { $this->_debug->query->select->total++; @@ -230,65 +348,259 @@ class MySQL { } // Analytics - public function getPeerFirst() { + public function getPeerFirstByTimeAdded() { $this->_debug->query->select->total++; - $query = $this->_db->prepare('SELECT * FROM `peer` ORDER BY `peerId` ASC LIMIT 1'); + $query = $this->_db->prepare('SELECT * FROM `peer` ORDER BY `timeAdded` ASC LIMIT 1'); $query->execute(); return $query->fetch(); } - public function getPeerTotal() { + public function findPeerSessionReceivedSumByTimeUpdated(int $timeFrom, int $timeTo, int $requestPeerId = 0) : int { $this->_debug->query->select->total++; - $query = $this->_db->prepare('SELECT COUNT(*) AS `total` FROM `peer`'); + $query = $this->_db->prepare('SELECT SUM(`received`) AS `result` - $query->execute(); + FROM `peerSession` + WHERE `timeUpdated` >= :timeFrom AND `timeUpdated` <= :timeTo' . ($requestPeerId > 0 ? ' AND `peerId` = ' . (int) $requestPeerId : false)); - return $query->fetch()->total; + $query->execute( + [ + ':timeFrom' => $timeFrom, + ':timeTo' => $timeTo + ] + ); + + return (int) $query->fetch()->result; } - public function findPeerTotalByTime(int $timeUpdatedFrom, int $timeUpdatedTo) : int { + public function findPeerSessionSentSumByTimeUpdated(int $timeFrom, int $timeTo, int $requestPeerId = 0) : int { $this->_debug->query->select->total++; - $query = $this->_db->prepare('SELECT COUNT(DISTINCT `peerId`) AS `total` FROM `peerRemote` WHERE (`timeAdded` > ? AND `timeAdded` < ?) OR (`timeUpdated` > ? AND `timeUpdated` < ?)'); + $query = $this->_db->prepare('SELECT SUM(`sent`) AS `result` + + FROM `peerSession` + WHERE `timeUpdated` >= :timeFrom AND `timeUpdated` <= :timeTo' . ($requestPeerId > 0 ? ' AND `peerId` = ' . (int) $requestPeerId : false)); - $query->execute([$timeUpdatedFrom, $timeUpdatedTo, $timeUpdatedFrom, $timeUpdatedTo]); + $query->execute( + [ + ':timeFrom' => $timeFrom, + ':timeTo' => $timeTo + ] + ); - return (int) $query->fetch()->total; + return (int) $query->fetch()->result; } - public function findPeerRemoteReceivedSumByTime(int $timeUpdatedFrom, int $timeUpdatedTo) : int { + public function findPeerTotalByTimeAdded(int $timeFrom, int $timeTo, int $requestPeerId = 0) : int { $this->_debug->query->select->total++; - $query = $this->_db->prepare('SELECT SUM(`received`) AS `result` FROM `peerRemote` WHERE (`timeAdded` > ? AND `timeAdded` < ?) OR (`timeUpdated` > ? AND `timeUpdated` < ?)'); + $query = $this->_db->prepare('SELECT COUNT(DISTINCT `peerId`) AS `result` + + FROM `peerSession` WHERE `timeAdded` >= :timeFrom AND `timeAdded` <= :timeTo' . - $query->execute([$timeUpdatedFrom, $timeUpdatedTo, $timeUpdatedFrom, $timeUpdatedTo]); + ($requestPeerId > 0 ? ' AND `peerId` = ' . (int) $requestPeerId : false)); + + $query->execute( + [ + ':timeFrom' => $timeFrom, + ':timeTo' => $timeTo + ] + ); return (int) $query->fetch()->result; } - public function findPeerRemoteSentSumByTime(int $timeUpdatedFrom, int $timeUpdatedTo) : int { + public function findPeerTotalByTimeUpdated(int $timeFrom, int $timeTo, int $requestPeerId = 0) : int { $this->_debug->query->select->total++; - $query = $this->_db->prepare('SELECT SUM(`sent`) AS `result` FROM `peerRemote` WHERE (`timeAdded` > ? AND `timeAdded` < ?) OR (`timeUpdated` > ? AND `timeUpdated` < ?)'); + $query = $this->_db->prepare('SELECT COUNT(DISTINCT `peerId`) AS `result` - $query->execute([$timeUpdatedFrom, $timeUpdatedTo, $timeUpdatedFrom, $timeUpdatedTo]); + FROM `peerSession` WHERE (`timeUpdated` >= :timeFrom AND `timeUpdated` <= :timeTo)' . + + ($requestPeerId > 0 ? ' AND `peerId` = ' . (int) $requestPeerId : false)); + + $query->execute( + [ + ':timeFrom' => $timeFrom, + ':timeTo' => $timeTo + ] + ); return (int) $query->fetch()->result; } + // Month page + public function findPeers(int $start = 0, int $limit = 20, string $sort = 'timeOnline', string $order = 'DESC') { + + if (!in_array($sort, + [ + 'timeOnline', + 'uptimeAvg', + 'sentSum', + 'receivedSum', + 'address', + ])) { + $sort = 'timeOnline'; + } + + if (!in_array($order, + [ + 'ASC', + 'DESC', + ])) { + $order = 'DESC'; + } + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT + + `peer`.`peerId`, + `peer`.`address`, + + (SELECT MAX(`peerSession`.`timeUpdated`) FROM `peerSession` WHERE `peerSession`.`peerId` = `peer`.`peerId`) AS `timeOnline`, + (SELECT SUM(`peerSession`.`sent`) FROM `peerSession` WHERE `peerSession`.`peerId` = `peer`.`peerId`) AS `sentSum`, + (SELECT SUM(`peerSession`.`received`) FROM `peerSession` WHERE `peerSession`.`peerId` = `peer`.`peerId`) AS `receivedSum`, + (SELECT AVG(`peerSession`.`uptime`) FROM `peerSession` WHERE `peerSession`.`peerId` = `peer`.`peerId`) AS `uptimeAvg` + + FROM `peer` + + GROUP BY `peer`.`peerId` + + ORDER BY ' . $sort . ' ' . $order . ' + + LIMIT ' . (int) $start . ', ' . (int) $limit); + + $query->execute(); + + return $query->fetchAll(); + } + + // Peer page + public function findPeerPeerConnections(int $peerId, int $start = 0, int $limit = 20, string $sort = 'timeOnline', string $order = 'DESC') { + + if (!in_array($sort, + [ + 'peerConnection.timeAdded', + ])) { + $sort = 'peerConnection.timeAdded'; + } + + if (!in_array($order, + [ + 'ASC', + 'DESC', + ])) { + $order = 'DESC'; + } + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare("SELECT + + MAX(`peerSession`.`timeUpdated`) AS `timeOnline`, + + `peerConnection`.`peerRemoteId`, + `peerConnection`.`timeAdded`, + + `peerRemoteScheme`.`name` AS `remoteScheme`, + `peerRemoteHost`.`name` AS `remoteHost`, + `peerRemotePort`.`name` AS `remotePort`, + + `peerCoordinate`.`port` AS `connectionPort`, + + CONCAT + ( + IF (`peerRemotePort`.`name` IS NOT NULL, + CONCAT(`peerRemoteScheme`.`name`, '://', `peerRemoteHost`.`name`, ':', `peerRemotePort`.`name`), + CONCAT(`peerRemoteScheme`.`name`, '://', `peerRemoteHost`.`name`) + ) + ) AS `remote`, + + ( + SELECT GROUP_CONCAT(`port` SEPARATOR ' → ') + FROM `peerCoordinateRoute` + WHERE `peerCoordinateRoute`.`peerCoordinateId` = `peerConnection`.`peerCoordinateId` + ORDER BY `peerCoordinateRoute`.`level` ASC + ) AS `route` + + FROM `peerConnection` + + JOIN `peerSession` ON (`peerSession`.`peerSessionId` = `peerConnection`.`peerSessionId`) + JOIN `peerRemote` ON (`peerRemote`.`peerRemoteId` = `peerConnection`.`peerRemoteId`) + JOIN `peerCoordinate` ON (`peerCoordinate`.`peerCoordinateId` = `peerConnection`.`peerCoordinateId`) + + JOIN `peerRemoteScheme` ON (`peerRemoteScheme`.`peerRemoteSchemeId` = `peerRemote`.`peerRemoteSchemeId`) + JOIN `peerRemoteHost` ON (`peerRemoteHost`.`peerRemoteHostId` = `peerRemote`.`peerRemoteHostId`) + JOIN `peerRemotePort` ON (`peerRemotePort`.`peerRemotePortId` = `peerRemote`.`peerRemotePortId`) + + JOIN `peer` ON (`peer`.`peerId` = `peerRemote`.`peerId`) + + WHERE `peerRemote`.`peerId` = :peerId + + GROUP BY `peerConnection`.`peerConnectionId` + + ORDER BY " . $sort . " " . $order . " + + LIMIT " . (int) $start . ", " . (int) $limit); + + $query->execute( + [ + ':peerId' => $peerId, + ] + ); + + return $query->fetchAll(); + } + + public function getPeerInfo(int $peerId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT + + `peer`.`peerId`, + `peer`.`key`, + `peer`.`address`, + `peer`.`timeAdded`, + + MAX(`peerSession`.`timeUpdated`) AS `timeOnline`, + SUM(`peerSession`.`sent`) AS `sentSum`, + SUM(`peerSession`.`received`) AS `receivedSum`, + ROUND(AVG(`peerSession`.`uptime`)) AS `uptimeAvg`, + + (SELECT COUNT(*) FROM `peerSession` WHERE `peerSession`.`peerId` = `peer`.`peerId`) AS `sessionTotal`, + (SELECT COUNT(*) FROM `peerRemote` WHERE `peerRemote`.`peerId` = `peer`.`peerId`) AS `remoteTotal`, + (SELECT COUNT(*) FROM `peerCoordinate` WHERE `peerCoordinate`.`peerId` = `peer`.`peerId`) AS `coordinateTotal` + + FROM `peer` + JOIN `peerSession` ON (`peerSession`.`peerId` = `peer`.`peerId`) + + WHERE `peer`.`peerId` = ? + + GROUP BY `peer`.`peerId` + + LIMIT 1'); + + $query->execute([$peerId]); + + return $query->fetch(); + } + // Other public function optimize() { $this->_db->query('OPTIMIZE TABLE `peer`'); $this->_db->query('OPTIMIZE TABLE `peerRemote`'); + $this->_db->query('OPTIMIZE TABLE `peerCoordinate`'); + $this->_db->query('OPTIMIZE TABLE `peerCoordinateRoute`'); } }