[FIX] Inifite loop on archive_cleanup

Fixes an infinite loop in cleaning up the archive table:

* Shares come in faster than defined in cleanup sleep timeout

Will use an upper limit ID which would match the delete query at the
initial state. Skips archiving if no ID is found (e.g. no rows match the
archive purge conditions).

This will fix #997 once merged.
This commit is contained in:
Sebastian Grewe 2013-12-16 16:50:39 +01:00
parent 8275e06fcc
commit 35ab40cbb7

View File

@ -175,30 +175,40 @@ class Share Extends Base {
if (!isset($this->config['purge']['shares'])) $this->config['purge']['shares'] = 25000;
if (!isset($this->config['purge']['sleep'])) $this->config['purge']['sleep'] = 1;
// TODO: This could need some cleanup work somtime but works
if ($this->config['payout_system'] == 'pplns') {
// Fetch our last block so we can go back configured rounds
$aLastBlock = $this->block->getLast();
// Fetch the block we need to find the share_id
$aBlock = $this->block->getBlock($aLastBlock['height'] - $this->config['archive']['maxrounds']);
// We need to find a hard limit id so we don't run into an infinite loop, skip process if we can't find a limit
$stmt = $this->mysqli->prepare("SELECT MAX(id) AS id FROM $this->tableArchive WHERE block_id < ? AND time < DATE_SUB(now(), INTERVAL ? MINUTE)");
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $aBlock['id'], $this->config['archive']['maxage']) && $stmt->execute() && $result = $stmt->get_result())
if ( ! $max_id = $result->fetch_object()->id ) return true;
// Now that we know our block, remove those shares
$affected = 1;
while ($affected > 0) {
// Sleep first to allow any IO to cleanup
sleep($this->config['purge']['sleep']);
$stmt = $this->mysqli->prepare("DELETE FROM $this->tableArchive WHERE block_id < ? AND time < DATE_SUB(now(), INTERVAL ? MINUTE) LIMIT " . $this->config['purge']['shares']);
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $aBlock['id'], $this->config['archive']['maxage']) && $stmt->execute()) {
$stmt = $this->mysqli->prepare("DELETE FROM $this->tableArchive WHERE block_id < ? AND time < DATE_SUB(now(), INTERVAL ? MINUTE) AND id <= ? LIMIT " . $this->config['purge']['shares']);
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $aBlock['id'], $this->config['archive']['maxage'], $max_id) && $stmt->execute()) {
$affected = $stmt->affected_rows;
} else {
return $this->sqlError();
}
}
} else {
// We need to find a hard limit id so we don't run into an infinite loop, skip process if we can't find a limit
$stmt = $this->mysqli->prepare("SELECT MAX(id) AS id FROM $this->tableArchive WHERE time < DATE_SUB(now(), INTERVAL ? MINUTE)");
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $this->config['archive']['maxage']) && $stmt->execute() && $result = $stmt->get_result())
if ( ! $max_id = $result->fetch_object()->id ) return true;
$affected = 1;
while ($affected > 0) {
// Sleep first to allow any IO to cleanup
sleep($this->config['purge']['sleep']);
$stmt = $this->mysqli->prepare("DELETE FROM $this->tableArchive WHERE time < DATE_SUB(now(), INTERVAL ? MINUTE) LIMIT " . $this->config['purge']['shares']);
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $this->config['archive']['maxage']) && $stmt->execute()) {
$stmt = $this->mysqli->prepare("DELETE FROM $this->tableArchive WHERE time < DATE_SUB(now(), INTERVAL ? MINUTE) AND id <= ? LIMIT " . $this->config['purge']['shares']);
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $this->config['archive']['maxage'], $max_id) && $stmt->execute()) {
$affected = $stmt->affected_rows;
} else {
return $this->sqlError();