Skip to content

Commit fe16f39

Browse files
s3inlcjessevz
andauthored
added multicolumn aggregation to DBA and improved three essential parts which suffer from many chunks (#1069)
* Adding loops to scan through lines to support importing hashes longer then 1024 bytes * added multicolumn aggregation to DBA and improved three essential parts which suffer from many chunks * applied requested changes (constants and query merge) for pull request #1069 --------- Co-authored-by: Jesse van Zutphen <[email protected]>
1 parent fd5ba50 commit fe16f39

File tree

6 files changed

+118
-41
lines changed

6 files changed

+118
-41
lines changed

src/dba/AbstractModelFactory.class.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,31 @@ public function minMaxFilter($options, $sumColumn, $op) {
411411
return $row['column_' . strtolower($op)];
412412
}
413413

414+
public function multicolAggregationFilter($options, $aggregations) {
415+
//$options: as usual
416+
//$columns: array of Aggregation objects
417+
418+
$elements = [];
419+
foreach ($aggregations as $aggregation) {
420+
$elements[] = $aggregation->getQueryString();
421+
}
422+
423+
$query = "SELECT " . join(",", $elements);
424+
$query = $query . " FROM " . $this->getModelTable();
425+
426+
$vals = array();
427+
428+
if (array_key_exists("filter", $options)) {
429+
$query .= $this->applyFilters($vals, $options['filter']);
430+
}
431+
432+
$dbh = self::getDB();
433+
$stmt = $dbh->prepare($query);
434+
$stmt->execute($vals);
435+
436+
return $stmt->fetch(PDO::FETCH_ASSOC);
437+
}
438+
414439
public function sumFilter($options, $sumColumn) {
415440
$query = "SELECT SUM($sumColumn) AS sum ";
416441
$query = $query . " FROM " . $this->getModelTable();

src/dba/Aggregation.class.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace DBA;
4+
5+
use DBA\AbstractModelFactory;
6+
7+
class Aggregation {
8+
private $column;
9+
private $function;
10+
/**
11+
* @var AbstractModelFactory
12+
*/
13+
private $factory;
14+
15+
const SUM = "SUM";
16+
const MAX = "MAX";
17+
const MIN = "MIN";
18+
const COUNT = "COUNT";
19+
20+
function __construct($column, $function, $factory = null) {
21+
$this->column = $column;
22+
$this->function = $function;
23+
$this->factory = $factory;
24+
}
25+
26+
function getName() {
27+
return strtolower($this->function) . "_" . $this->column;
28+
}
29+
30+
function getQueryString($table = "") {
31+
if ($table != "") {
32+
$table = $table . ".";
33+
}
34+
if ($this->factory != null) {
35+
$table = $this->factory->getModelTable() . ".";
36+
}
37+
38+
return $this->function . "(" . $table . $this->column . ") AS " . $this->getName();
39+
}
40+
}
41+
42+

src/dba/init.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
require_once(dirname(__FILE__) . "/AbstractModel.class.php");
1111
require_once(dirname(__FILE__) . "/AbstractModelFactory.class.php");
12+
require_once(dirname(__FILE__) . "/Aggregation.class.php");
1213
require_once(dirname(__FILE__) . "/Filter.class.php");
1314
require_once(dirname(__FILE__) . "/Order.class.php");
1415
require_once(dirname(__FILE__) . "/Join.class.php");

src/inc/Util.class.php

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?php
22

3+
use DBA\Aggregation;
34
use DBA\AbstractModel;
45
use DBA\AccessGroup;
56
use DBA\AccessGroupUser;
@@ -377,33 +378,33 @@ public static function insertFile($path, $name, $type, $accessGroupId) {
377378
* @return array
378379
*/
379380
public static function getTaskInfo($task) {
380-
$qF = new QueryFilter(Chunk::TASK_ID, $task->getId(), "=");
381-
$chunks = Factory::getChunkFactory()->filter([Factory::FILTER => $qF]);
382-
$progress = 0;
383-
$cracked = 0;
384-
$maxTime = 0;
385-
$totalTimeSpent = 0;
386-
$speed = 0;
387-
foreach ($chunks as $chunk) {
388-
if ($chunk->getDispatchTime() > 0 && $chunk->getSolveTime() > 0) {
389-
$totalTimeSpent += $chunk->getSolveTime() - $chunk->getDispatchTime();
390-
}
391-
$progress += $chunk->getCheckpoint() - $chunk->getSkip();
392-
$cracked += $chunk->getCracked();
393-
if ($chunk->getDispatchTime() > $maxTime) {
394-
$maxTime = $chunk->getDispatchTime();
395-
}
396-
if ($chunk->getSolveTime() > $maxTime) {
397-
$maxTime = $chunk->getSolveTime();
398-
}
399-
$speed += $chunk->getSpeed();
400-
}
381+
$qF1 = new QueryFilter(Chunk::TASK_ID, $task->getId(), "=");
382+
383+
$agg1 = new Aggregation(Chunk::CHECKPOINT, Aggregation::SUM);
384+
$agg2 = new Aggregation(Chunk::SKIP, Aggregation::SUM);
385+
$agg3 = new Aggregation(Chunk::CRACKED, Aggregation::SUM);
386+
$agg4 = new Aggregation(Chunk::SPEED, Aggregation::SUM);
387+
$agg5 = new Aggregation(Chunk::DISPATCH_TIME, Aggregation::MAX);
388+
$agg6 = new Aggregation(Chunk::SOLVE_TIME, Aggregation::MAX);
389+
$agg7 = new Aggregation(Chunk::CHUNK_ID, Aggregation::COUNT);
390+
$agg8 = new Aggregation(Chunk::SOLVE_TIME, Aggregation::SUM);
391+
$agg9 = new Aggregation(Chunk::DISPATCH_TIME, Aggregation::SUM);
392+
393+
$results = Factory::getChunkFactory()->multicolAggregationFilter([Factory::FILTER => $qF1], [$agg1, $agg2, $agg3, $agg4, $agg5, $agg6, $agg7, $agg8, $agg9]);
394+
395+
$totalTimeSpent = $results[$agg8->getName()] - $results[$agg9->getName()];
396+
397+
$progress = $results[$agg1->getName()] - $results[$agg2->getName()];
398+
$cracked = $results[$agg3->getName()];
399+
$speed = $results[$agg4->getName()];
400+
$maxTime = max($results[$agg5->getName()], $results[$agg6->getName()]);
401+
$numChunks = $results[$agg7->getName()];
401402

402403
$isActive = false;
403404
if (time() - $maxTime < SConfig::getInstance()->getVal(DConfig::CHUNK_TIMEOUT) && ($progress < $task->getKeyspace() || $task->getUsePreprocessor() && $task->getKeyspace() == DPrince::PRINCE_KEYSPACE)) {
404405
$isActive = true;
405406
}
406-
return array($progress, $cracked, $isActive, sizeof($chunks), ($totalTimeSpent > 0) ? round($cracked * 60 / $totalTimeSpent, 2) : 0, $speed);
407+
return array($progress, $cracked, $isActive, $numChunks, ($totalTimeSpent > 0) ? round($cracked * 60 / $totalTimeSpent, 2) : 0, $speed);
407408
}
408409

409410
/**
@@ -438,8 +439,12 @@ public static function getFileInfo($task, $accessGroups) {
438439
*/
439440
public static function getChunkInfo($task) {
440441
$qF = new QueryFilter(Chunk::TASK_ID, $task->getId(), "=");
441-
$cracked = Factory::getChunkFactory()->sumFilter([Factory::FILTER => $qF], Chunk::CRACKED);
442-
$numChunks = Factory::getChunkFactory()->countFilter([Factory::FILTER => $qF]);
442+
$agg1 = new Aggregation(Chunk::CRACKED, "SUM");
443+
$agg2 = new Aggregation(Chunk::CHUNK_ID, "COUNT");
444+
$results = Factory::getChunkFactory()->multicolAggregationFilter([Factory::FILTER => $qF], [$agg1, $agg2]);
445+
446+
$cracked = $results[$agg1->getName()];
447+
$numChunks = $results[$agg2->getName()];
443448

444449
$qF = new QueryFilter(Assignment::TASK_ID, $task->getId(), "=");
445450
$numAssignments = Factory::getAssignmentFactory()->countFilter([Factory::FILTER => $qF]);

src/inc/api/APIGetChunk.class.php

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,10 @@ public function execute($QUERY = array()) {
6666
DServerLog::log(DServerLog::TRACE, "Agent is inactive!", [$this->agent]);
6767
$this->sendErrorResponse(PActions::GET_CHUNK, "Agent is inactive!");
6868
}
69+
70+
$LOCKFILE = LOCK::CHUNKING.$task->getId();
6971

70-
LockUtils::get(Lock::CHUNKING);
72+
LockUtils::get($LOCKFILE);
7173
DServerLog::log(DServerLog::TRACE, "Retrieved lock for chunking!", [$this->agent]);
7274
$task = Factory::getTaskFactory()->get($task->getId());
7375
Factory::getAgentFactory()->getDB()->beginTransaction();
@@ -76,7 +78,7 @@ public function execute($QUERY = array()) {
7678
if ($task == null) { // agent needs a new task
7779
DServerLog::log(DServerLog::DEBUG, "Task is fully dispatched", [$this->agent]);
7880
Factory::getAgentFactory()->getDB()->commit();
79-
LockUtils::release(Lock::CHUNKING);
81+
LockUtils::release($LOCKFILE);
8082
DServerLog::log(DServerLog::TRACE, "Released lock for chunking!", [$this->agent]);
8183
$this->sendResponse(array(
8284
PResponseGetChunk::ACTION => PActions::GET_CHUNK,
@@ -93,22 +95,22 @@ public function execute($QUERY = array()) {
9395
// this is a special case where this task is either not allowed anymore, or it has priority 0 so it doesn't get auto assigned
9496
if (!AccessUtils::agentCanAccessTask($this->agent, $task)) {
9597
Factory::getAgentFactory()->getDB()->commit();
96-
LockUtils::release(Lock::CHUNKING);
98+
LockUtils::release($LOCKFILE);
9799
DServerLog::log(DServerLog::INFO, "Not allowed to work on requested task", [$this->agent, $task]);
98100
DServerLog::log(DServerLog::TRACE, "Released lock for chunking!", [$this->agent]);
99101
$this->sendErrorResponse(PActions::GET_CHUNK, "Not allowed to work on this task!");
100102
}
101103
if (TaskUtils::isSaturatedByOtherAgents($task, $this->agent)) {
102104
Factory::getAgentFactory()->getDB()->commit();
103-
LockUtils::release(Lock::CHUNKING);
105+
LockUtils::release($LOCKFILE);
104106
DServerLog::log(DServerLog::TRACE, "Released lock for chunking!", [$this->agent]);
105107
$this->sendErrorResponse(PActions::GET_CHUNK, "Task already saturated by other agents, no other task available!");
106108
}
107109
}
108110

109111
if (TaskUtils::isSaturatedByOtherAgents($task, $this->agent)) {
110112
Factory::getAgentFactory()->getDB()->commit();
111-
LockUtils::release(Lock::CHUNKING);
113+
LockUtils::release($LOCKFILE);
112114
DServerLog::log(DServerLog::TRACE, "Released lock for chunking!", [$this->agent]);
113115
$this->sendErrorResponse(PActions::GET_CHUNK, "Task already saturated by other agents, other tasks available!");
114116
}
@@ -119,7 +121,7 @@ public function execute($QUERY = array()) {
119121
if ($bestTask->getId() != $task->getId()) {
120122
Factory::getAgentFactory()->getDB()->commit();
121123
DServerLog::log(DServerLog::INFO, "Task with higher priority available!", [$this->agent]);
122-
LockUtils::release(Lock::CHUNKING);
124+
LockUtils::release($LOCKFILE);
123125
DServerLog::log(DServerLog::TRACE, "Released lock for chunking!", [$this->agent]);
124126
$this->sendErrorResponse(PActions::GET_CHUNK, "Task with higher priority available!");
125127
}
@@ -150,7 +152,7 @@ public function execute($QUERY = array()) {
150152
if ($chunk == null) {
151153
DServerLog::log(DServerLog::DEBUG, "Could not create a chunk, task is fully dispatched", [$this->agent, $task]);
152154
Factory::getAgentFactory()->getDB()->commit();
153-
LockUtils::release(Lock::CHUNKING);
155+
LockUtils::release($LOCKFILE);
154156
DServerLog::log(DServerLog::TRACE, "Released lock for chunking!", [$this->agent]);
155157
$this->sendResponse(array(
156158
PResponseGetChunk::ACTION => PActions::GET_CHUNK,
@@ -171,7 +173,7 @@ protected function sendChunk($chunk) {
171173
return; // this can be safely done before the commit/release, because the only sendChunk which comes really at the end check for null before, so a lock which is not released cannot happen
172174
}
173175
Factory::getAgentFactory()->getDB()->commit();
174-
LockUtils::release(Lock::CHUNKING);
176+
LockUtils::release(Lock::CHUNKING.$chunk->getTaskId());
175177
DServerLog::log(DServerLog::TRACE, "Released lock for chunking!", [$this->agent]);
176178
$this->sendResponse(array(
177179
PResponseGetChunk::ACTION => PActions::GET_CHUNK,

src/inc/utils/TaskUtils.class.php

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,18 +1152,20 @@ public static function checkTask($task, $agent = null) {
11521152
else if ($task->getUsePreprocessor() && $task->getKeyspace() == DPrince::PRINCE_KEYSPACE) {
11531153
return $task;
11541154
}
1155+
1156+
$qF1 = new QueryFilter(Chunk::TASK_ID, $task->getId(), "=");
1157+
$qF2 = new QueryFilter(Chunk::PROGRESS, 10000, ">=");
1158+
$sum = Factory::getChunkFactory()->sumFilter([Factory::FILTER => [$qF1, $qF2]], Chunk::LENGTH);
1159+
1160+
$dispatched = $task->getSkipKeyspace() + $sum;
1161+
$completed = $task->getSkipKeyspace() + $sum;
11551162

11561163
// check chunks
1157-
$qF = new QueryFilter(Chunk::TASK_ID, $task->getId(), "=");
1158-
$chunks = Factory::getChunkFactory()->filter([Factory::FILTER => $qF]);
1159-
$dispatched = $task->getSkipKeyspace();
1160-
$completed = $task->getSkipKeyspace();
1164+
$qF1 = new QueryFilter(Chunk::TASK_ID, $task->getId(), "=");
1165+
$qF2 = new QueryFilter(Chunk::PROGRESS, 10000, "<");
1166+
$chunks = Factory::getChunkFactory()->filter([Factory::FILTER => [$qF1, $qF2]]);
11611167
foreach ($chunks as $chunk) {
1162-
if ($chunk->getProgress() >= 10000) {
1163-
$dispatched += $chunk->getLength();
1164-
$completed += $chunk->getLength();
1165-
}
1166-
else if ($chunk->getAgentId() == null) {
1168+
if ($chunk->getAgentId() == null) {
11671169
return $task; // at least one chunk is not assigned
11681170
}
11691171
else if (time() - max($chunk->getSolveTime(), $chunk->getDispatchTime()) > SConfig::getInstance()->getVal(DConfig::AGENT_TIMEOUT)) {

0 commit comments

Comments
 (0)