From 78619c1427bb33295f0b8696d2aecda48026a166 Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Wed, 26 Feb 2014 09:27:32 +0100 Subject: [PATCH 1/2] [IMPROVED] Unified user speed statistics * [ADDED] getUserMiningStats to fetch all speed related data * Uses global cache if available, falls back to local query and then local caches * [REMOVED] getUserHashrate, getUserSharerate, getUserAvgShareDifficulty * [UPDATED] All code occurences for the above to use the new system Probably won't change much since global cache was already used but does help on the Dashboard since we combine at least 2 calls into one. --- public/include/classes/statistics.class.php | 97 +++---------------- public/include/pages/admin/user.inc.php | 7 +- .../pages/api/getdashboarddata.inc.php | 7 +- .../include/pages/api/getuserhashrate.inc.php | 3 +- .../pages/api/getusersharerate.inc.php | 3 +- .../include/pages/api/getuserstatus.inc.php | 11 ++- public/include/smarty_globals.inc.php | 5 +- 7 files changed, 38 insertions(+), 95 deletions(-) diff --git a/public/include/classes/statistics.class.php b/public/include/classes/statistics.class.php index 5b1e94be..95310e8f 100644 --- a/public/include/classes/statistics.class.php +++ b/public/include/classes/statistics.class.php @@ -489,47 +489,6 @@ class Statistics extends Base { } } - /** - * Fetch total user hashrate based on shares and archived shares - * @param $username string username - * @param $account_id int account id - * @return data integer Current Hashrate in khash/s - **/ - public function getUserHashrate($username, $account_id=NULL, $interval=180) { - $this->debug->append("STA " . __METHOD__, 4); - // Dual-caching, try statistics cron first, then fallback to local, then fallbock to SQL - if ($this->getGetCache() && $data = $this->memcache->getStatic(STATISTICS_ALL_USER_HASHRATES)) { - if (array_key_exists($account_id, $data['data'])) - return $data['data'][$account_id]['hashrate']; - // We have no cached value, we return defaults - return 0; - } - if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data; - $stmt = $this->mysqli->prepare(" - SELECT - IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * POW(2, " . $this->config['target_bits'] . ") / ? / 1000), 0), 0) AS hashrate - FROM ( - SELECT - id, our_result, IF(difficulty = 0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty - FROM - shares - WHERE username LIKE ? - AND time > DATE_SUB(now(), INTERVAL ? SECOND) - AND our_result = 'Y' - UNION - SELECT - share_id, our_result, IF(difficulty = 0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty - FROM - shares_archive - WHERE username LIKE ? - AND time > DATE_SUB(now(), INTERVAL ? SECOND) - AND our_result = 'Y') AS temp"); - $username = $username . ".%"; - if ($this->checkStmt($stmt) && $stmt->bind_param("isisi", $interval, $username, $interval, $username, $interval) && $stmt->execute() && $result = $stmt->get_result() ) - return $this->memcache->setCache(__FUNCTION__ . $account_id, (float)$result->fetch_object()->hashrate); - return $this->sqlError(); - } - public function getUserUnpaidPPSShares($username, $account_id=NULL, $last_paid_pps_id) { $this->debug->append("STA " . __METHOD__, 4); if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data; @@ -546,60 +505,32 @@ class Statistics extends Base { return $this->sqlError(); } - /** - * Get average share difficulty across all workers for user - * @param username string username - * @param $account_id int account id - * @param interval int Data interval in seconds - * @return double Share difficulty or 0 - **/ - public function getUserShareDifficulty($username, $account_id=NULL, $interval=180) { - $this->debug->append("STA " . __METHOD__, 4); - // Dual-caching, try statistics cron first, then fallback to local, then fallbock to SQL - if ($this->getGetCache() && $data = $this->memcache->getStatic(STATISTICS_ALL_USER_HASHRATES)) { - if (array_key_exists($account_id, $data['data'])) - return $data['data'][$account_id]['avgsharediff']; - // We have no cached value, we return defaults - return 0; - } - if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data; - $stmt = $this->mysqli->prepare(" - SELECT - IFNULL(AVG(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)), 0) AS avgsharediff, - COUNT(s.id) AS total - FROM " . $this->share->getTableName() . " AS s - WHERE username LIKE ? - AND time > DATE_SUB(now(), INTERVAL ? SECOND) - AND our_result = 'Y' - "); - $username = $username . ".%"; - if ($this->checkStmt($stmt) && $stmt->bind_param("si", $username, $interval) && $stmt->execute() && $result = $stmt->get_result() ) - return $this->memcache->setCache(__FUNCTION__ . $account_id, (float)$result->fetch_object()->avgsharediff); - return $this->sqlError(); - } - /** * Get Shares per x interval by user * @param username string username * @param $account_id int account id * @return data integer Current Sharerate in shares/s **/ - public function getUserSharerate($username, $account_id=NULL, $interval=180) { + public function getUserMiningStats($username, $account_id=NULL, $interval=180) { $this->debug->append("STA " . __METHOD__, 4); // Dual-caching, try statistics cron first, then fallback to local, then fallbock to SQL if ($this->getGetCache() && $data = $this->memcache->getStatic(STATISTICS_ALL_USER_HASHRATES)) { - if (array_key_exists($account_id, $data['data'])) - return $data['data'][$account_id]['sharerate']; - // We have no cached value, we return defaults - return 0; + if (array_key_exists($account_id, $data['data'])) { + $retData['hashrate'] = $data['data'][$account_id]['hashrate']; + $retData['sharerate'] = $data['data'][$account_id]['sharerate']; + $retData['avgsharediff'] = $data['data'][$account_id]['avgsharediff']; + return $retData; + } } if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data; $stmt = $this->mysqli->prepare(" SELECT - IFNULL(COUNT(*) / ?, 0) AS sharerate + IFNULL(COUNT(*) / ?, 0) AS sharerate, + IFNULL(ROUND(SUM(difficulty) * POW(2, " . $this->config['target_bits'] . ") / ? / 1000, 2), 0) AS hashrate, + IFNULL(AVG(difficulty), 0) AS avgsharediff FROM ( SELECT - id + id, our_result, IF(difficulty = 0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty FROM shares WHERE username LIKE ? @@ -607,7 +538,7 @@ class Statistics extends Base { AND our_result = 'Y' UNION SELECT - share_id + share_id, our_result, IF(difficulty = 0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty FROM shares_archive WHERE username LIKE ? @@ -615,8 +546,8 @@ class Statistics extends Base { AND our_result = 'Y' ) AS temp"); $username = $username . ".%"; - if ($this->checkStmt($stmt) && $stmt->bind_param("isisi", $interval, $username, $interval, $username, $interval) && $stmt->execute() && $result = $stmt->get_result() ) - return $this->memcache->setCache(__FUNCTION__ . $account_id, (float)$result->fetch_object()->sharerate); + if ($this->checkStmt($stmt) && $stmt->bind_param("iisisi", $interval, $interval, $username, $interval, $username, $interval) && $stmt->execute() && $result = $stmt->get_result() ) + return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_assoc()); return $this->sqlError(); } diff --git a/public/include/pages/admin/user.inc.php b/public/include/pages/admin/user.inc.php index cb49d6e0..5795bd50 100644 --- a/public/include/pages/admin/user.inc.php +++ b/public/include/pages/admin/user.inc.php @@ -58,11 +58,12 @@ if (isset($_REQUEST['filter'])) { $aBalance = $transaction->getBalance($aUser['id']); $aUser['balance'] = $aBalance['confirmed']; $aUser['signup_timestamp'] = $user->getSignupTime($aUser['id']); - $aUser['hashrate'] = $statistics->getUserHashrate($aUser['username'], $aUser['id']); + $aUserMiningStats = $statistics->getUserMiningStats($aUser['username'], $aUser['id']); + $aUser['hashrate'] = $aUserMiningStats['hashrate']; if ($config['payout_system'] == 'pps') { - $aUser['sharerate'] = $statistics->getUserSharerate($aUser['username'], $aUser['id']); - $aUser['difficulty'] = $statistics->getUserShareDifficulty($aUser['username'], $aUser['id']); + $aUser['sharerate'] = $aUserMiningStats['sharerate']; + $aUser['difficulty'] = $aUserMiningStats['avgsharediff']; $aUser['estimates'] = $statistics->getUserEstimates($aUser['sharerate'], $aUser['difficulty'], $user->getUserDonatePercent($aUser['id']), $user->getUserNoFee($aUser['id']), $statistics->getPPSValue()); } else { $aUser['estimates'] = $statistics->getUserEstimates($aRoundShares, $aUser['shares'], $aUser['donate_percent'], $aUser['no_fees']); diff --git a/public/include/pages/api/getdashboarddata.inc.php b/public/include/pages/api/getdashboarddata.inc.php index 9f7c6844..db70772a 100644 --- a/public/include/pages/api/getdashboarddata.inc.php +++ b/public/include/pages/api/getdashboarddata.inc.php @@ -43,9 +43,10 @@ if ( ! $dNetworkHashrateModifier = $setting->getValue('statistics_network_hashra $statistics->setGetCache(false); $dPoolHashrate = $statistics->getCurrentHashrate($interval); if ($dPoolHashrate > $dNetworkHashrate) $dNetworkHashrate = $dPoolHashrate; -$dPersonalHashrate = $statistics->getUserHashrate($username, $user_id, $interval); -$dPersonalSharerate = $statistics->getUserSharerate($username, $user_id, $interval); -$dPersonalShareDifficulty = $statistics->getUserShareDifficulty($username, $user_id, $interval); +$aUserMiningStats = $statistics->getUserMiningStats($username, $user_id, $interval); +$dPersonalHashrate = $aUserMiningStats['hashrate']; +$dPersonalSharerate = $aUserMiningStats['sharerate']; +$dPersonalShareDifficulty = $aUserMiningStats['avgsharediff']; $statistics->setGetCache(true); // Use caches for this one diff --git a/public/include/pages/api/getuserhashrate.inc.php b/public/include/pages/api/getuserhashrate.inc.php index 13f61a8c..e1970030 100644 --- a/public/include/pages/api/getuserhashrate.inc.php +++ b/public/include/pages/api/getuserhashrate.inc.php @@ -13,7 +13,8 @@ if ( ! $interval = $setting->getValue('statistics_ajax_data_interval')) $interva // Gather un-cached data $statistics->setGetCache(false); -$hashrate = $statistics->getUserHashrate($username, $user_id, $interval); +$aUserMiningStats = $statistics->getUserMiningStats($username, $user_id, $interval); +$hashrate = $aUserMiningStats['hashrate']; $statistics->setGetCache(true); // Output JSON diff --git a/public/include/pages/api/getusersharerate.inc.php b/public/include/pages/api/getusersharerate.inc.php index 86b3c762..99650085 100644 --- a/public/include/pages/api/getusersharerate.inc.php +++ b/public/include/pages/api/getusersharerate.inc.php @@ -13,7 +13,8 @@ if ( ! $interval = $setting->getValue('statistics_ajax_data_interval')) $interva // Gather un-cached data $statistics->setGetCache(false); -$sharerate = $statistics->getUserSharerate($username, $user_id, $interval); +$aUserMiningStats = $statistics->getUserMiningStats($username, $user_id, $interval); +$sharerate = $aUserMiningStats['sharerate']; $statistics->setGetCache(true); // Output JSON format diff --git a/public/include/pages/api/getuserstatus.inc.php b/public/include/pages/api/getuserstatus.inc.php index df514c9a..03b4053c 100644 --- a/public/include/pages/api/getuserstatus.inc.php +++ b/public/include/pages/api/getuserstatus.inc.php @@ -7,15 +7,22 @@ $api->isActive(); // Check user token $user_id = $api->checkAccess($user->checkApiKey($_REQUEST['api_key']), @$_REQUEST['id']); $username = $user->getUsername($user_id); + +// Fetch some settings +if ( ! $interval = $setting->getValue('statistics_ajax_data_interval')) $interval = 300; + // Fetch transaction summary $aTransactionSummary = $transaction->getTransactionSummary($user_id); +// User mining status +$aUserMiningStats = $statistics->getUserMiningStats($username, $user_id, $interval); + // Output JSON format $data = array( 'username' => $username, 'shares' => $statistics->getUserShares($username, $user_id), - 'hashrate' => $statistics->getUserHashrate($username, $user_id), - 'sharerate' => $statistics->getUserSharerate($username, $user_id) + 'hashrate' => $aUserMiningStats['hashrate'], + 'sharerate' => $aUserMiningStats['sharerate'] ); echo $api->get_json($data); diff --git a/public/include/smarty_globals.inc.php b/public/include/smarty_globals.inc.php index d36080f8..b85fbbf2 100644 --- a/public/include/smarty_globals.inc.php +++ b/public/include/smarty_globals.inc.php @@ -133,9 +133,10 @@ if (@$_SESSION['USERDATA']['id']) { // Other userdata that we can cache savely $aGlobal['userdata']['shares'] = $statistics->getUserShares($_SESSION['USERDATA']['username'], $_SESSION['USERDATA']['id']); - $aGlobal['userdata']['rawhashrate'] = $statistics->getUserHashrate($_SESSION['USERDATA']['username'], $_SESSION['USERDATA']['id']); + $aUserMiningStats = $statistics->getUserMiningStats($_SESSION['USERDATA']['username'], $_SESSION['USERDATA']['id']); + $aGlobal['userdata']['rawhashrate'] = $aUserMiningStats['hashrate']; $aGlobal['userdata']['hashrate'] = $aGlobal['userdata']['rawhashrate'] * $dPersonalHashrateModifier; - $aGlobal['userdata']['sharerate'] = $statistics->getUserSharerate($_SESSION['USERDATA']['username'], $_SESSION['USERDATA']['id']); + $aGlobal['userdata']['sharerate'] = $aUserMiningStats['sharerate']; switch ($config['payout_system']) { case 'prop': From d750e81b02c8ae2c0228fb416392f10416e16f7b Mon Sep 17 00:00:00 2001 From: Sebastian Grewe Date: Wed, 26 Feb 2014 09:42:49 +0100 Subject: [PATCH 2/2] [FIX] Wait for global cache data, don't run queries --- public/include/classes/statistics.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/public/include/classes/statistics.class.php b/public/include/classes/statistics.class.php index 95310e8f..5b2eeacf 100644 --- a/public/include/classes/statistics.class.php +++ b/public/include/classes/statistics.class.php @@ -521,6 +521,7 @@ class Statistics extends Base { $retData['avgsharediff'] = $data['data'][$account_id]['avgsharediff']; return $retData; } + return array('hashrate' => (float)0, 'sharerate' => (float)0, 'avgsharediff' => (float)0); } if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data; $stmt = $this->mysqli->prepare("