/** * updateStatFiles * * @param $transfer string torrent name * @return boolean */ function updateStatFiles($transfer = "") { global $cfg, $db; //$rpc = Transmission::getInstance(); $tfs = $this->monitorRunningTransfers(); if (!is_array($tfs)) { return false; } $sql = "SELECT hash, transfer, sharekill FROM tf_transfers WHERE type='torrent' AND client = 'transmissionrpc'"; if ($transfer != "") { //only update one transfer... $sql .= " AND transfer=" . $db->qstr($transfer); } else { $hashes = array("''"); foreach ($tfs as $hash => $t) { $hashes[] = "'" . strtolower($hash) . "'"; } $sql .= " AND hash IN (" . implode(',', $hashes) . ")"; } $recordset = $db->Execute($sql); while (list($hash, $transfer, $sharekill) = $recordset->FetchRow()) { $hash = strtolower($hash); $hashes[$hash] = $transfer; $sharekills[$hash] = $sharekill; } //convertTimeText require_once "inc/functions/functions.core.php"; foreach ($tfs as $hash => $t) { if (!isset($hashes[$hash])) { continue; } $transfer = $hashes[$hash]; $sf = new StatFile($transfer); $sf->running = $t['running']; $sf->percent_done = round($t['percentDone'] * 100, 2); if ($t['status'] == 8 || $t['status'] == 9) { $sf->sharing = round($t['uploadRatio'] * 100, 2); } $sf->downtotal = $t['downloadedEver']; $sf->uptotal = $t['uploadedEver']; $sf->write(); } //SHAREKILLS Checks foreach ($tfs as $hash => $t) { if (!isset($sharekills[$hash])) { continue; } if (($t['status'] == 8 || $t['status'] == 9) && $t['uploadRatio'] * 100 > $sharekills[$hash]) { $transfer = $hashes[$hash]; if (stopTransmissionTransfer($hash)) { AuditAction($cfg["constants"]["stop_transfer"], $this->client . "-stat. : sharekill stopped {$transfer}"); stopTransferSettings($transfer); } } } return true; }
/** * instance_dequeue * * @param $transfer * @param $user */ function instance_dequeueTransfer($transfer, $user) { global $cfg; if ($this->modstate == FLUXDMOD_STATE_RUNNING) { if (isTransferRunning($transfer)) { // transfer has been started...log AuditAction($cfg["constants"]["unqueued_transfer"], $transfer . "has been already started."); } else { // send command $result = Fluxd::sendServiceCommand($this->moduleName, 'dequeue;' . $transfer . ';' . $user, 1); // flag the transfer as stopped (in db) stopTransferSettings($transfer); // update the stat file. $this->_updateStatFile($transfer); // log AuditAction($cfg["constants"]["fluxd"], $result); // log AuditAction($cfg["constants"]["unqueued_transfer"], $transfer); // just 2 sec... dont stress fluxd sleep(2); } } }
/** * _maintenanceTransfers * * @param $trestart * @return boolean */ function _maintenanceTransfers($trestart = false) { global $cfg, $db, $transfers; // set var $this->_restartTransfers = $trestart; // output $this->_outputMessage("transfers-maintenance...\n"); // sanity-check for transfers-dir if (!is_dir($cfg["transfer_file_path"])) { $this->state = MAINTENANCEANDREPAIR_STATE_ERROR; $msg = "invalid dir-settings. no dir : " . $cfg["transfer_file_path"]; array_push($this->messages, $msg); $this->_outputError($msg . "\n"); return false; } // pid-files of transfer-clients $pidFiles = array(); if ($dirHandle = @opendir($cfg["transfer_file_path"])) { while (false !== ($file = @readdir($dirHandle))) { if (strlen($file) > 3 && substr($file, -4, 4) == ".pid") { array_push($pidFiles, $file); } } @closedir($dirHandle); } // return if no pid-files found if (count($pidFiles) < 1) { $this->_outputMessage("no pid-files found.\n"); $this->_outputMessage("transfers-maintenance done.\n"); return true; } // get process-list $psString = trim(shell_exec("ps x -o pid='' -o ppid='' -o command='' -ww")); // test if client for pid is still up $this->_bogusTransfers = array(); foreach ($pidFiles as $pidFile) { $transfer = substr($pidFile, 0, -4); if (stristr($psString, $transfer) === false) { if (getTransferClient($transfer) != "azureus") { array_push($this->_bogusTransfers, $transfer); } } } // return if no stale pid-files $this->_countProblems = count($this->_bogusTransfers); if ($this->_countProblems < 1) { $this->_outputMessage("no stale pid-files found.\n"); $this->_outputMessage("transfers-maintenance done.\n"); return true; } /* repair the bogus clients */ $this->_countFixed = 0; $this->_outputMessage("repairing died clients...\n"); foreach ($this->_bogusTransfers as $transfer) { // output $this->_outputMessage("repairing " . $transfer . " ...\n"); // set stopped flag in db stopTransferSettings($transfer); // rewrite stat-file $sf = new StatFile($transfer, getOwner($transfer)); $sf->running = 0; $sf->percent_done = -100.0; $sf->time_left = 'Transfer Died'; $sf->down_speed = 0; $sf->up_speed = 0; $sf->seeds = 0; $sf->peers = 0; $sf->write(); // delete pid-file @unlink($cfg["transfer_file_path"] . $transfer . ".pid"); // DEBUG : log the repair of the bogus transfer if ($cfg['debuglevel'] > 0) { AuditAction($cfg["constants"]["debug"], "transfers-maintenance : transfer repaired : " . $transfer); } // output $this->_outputMessage("done.\n"); // count $this->_countFixed++; } // output if ($this->_countProblems > 0) { $this->_outputMessage("repaired transfers : " . $this->_countFixed . "/" . $this->_countProblems . "\n"); } /* restart transfers */ if ($this->_restartTransfers) { $this->_fixedTransfers = array(); $this->_outputMessage("restarting died clients...\n"); // hold current user $whoami = $this->_mode == MAINTENANCEANDREPAIR_MODE_CLI ? GetSuperAdmin() : $cfg["user"]; foreach ($this->_bogusTransfers as $transfer) { // output $this->_outputMessage("Starting " . $transfer . " ...\n"); // set current user to transfer-owner $cfg["user"] = getOwner($transfer); // clientHandler + start $ch = ClientHandler::getInstance(getTransferClient($transfer)); $ch->start($transfer, false, FluxdQmgr::isRunning()); // DEBUG : log the restart of the died transfer if ($cfg['debuglevel'] > 0) { $staret = $ch->state == CLIENTHANDLER_STATE_OK ? "OK" : "FAILED"; AuditAction($cfg["constants"]["debug"], "transfers-maintenance : restarted transfer " . $transfer . " by " . $whoami . " : " . $staret); } if ($ch->state == CLIENTHANDLER_STATE_OK) { // output $this->_outputMessage("done.\n"); // add to ary array_push($this->_fixedTransfers, $transfer); // count $this->_countFixed++; } else { $this->messages = array_merge($this->messages, $ch->messages); $this->_outputError(implode("\n", $ch->messages) . "\n"); } } // set user back $cfg["user"] = $whoami; // output $this->_countFixed = count($this->_fixedTransfers); if ($this->_countFixed > 0) { $this->_outputMessage("restarted transfers : " . $this->_countFixed . "/" . $this->_countProblems . "\n"); } } /* done */ $this->_outputMessage("transfers-maintenance done.\n"); // return return true; }
/** * stop wrapper * * @param $error */ function _wrapperStop($error = false) { // output $this->_outputMessage("wget-wrapper shutting down...\n"); // stop client $this->_clientStop(); // transfer settings stopTransferSettings($this->_transfer); // stat $this->_statShutdown($error); // pid $this->_pidFileDelete(); // output $this->_outputMessage("wget-wrapper exit.\n"); // exit exit; }
/** * updateStatFiles * * @param $transfer string torrent name * @return boolean */ function updateStatFiles($transfer = "") { global $cfg, $db; $vuze = VuzeRPC::getInstance(); // do special-pre-start-checks if (!VuzeRPC::isRunning()) { return; } $tfs = $vuze->torrent_get_tf(); if (empty($tfs)) { return; } $sql = "SELECT hash, transfer, sharekill FROM tf_transfers WHERE type='torrent' AND client IN ('vuzerpc','azureus')"; if ($transfer != "") { //only update one transfer... $sql .= " AND transfer=" . $db->qstr($transfer); } else { //or a set of hashes $hashes = array("''"); foreach ($tfs as $hash => $t) { $hashes[] = "'" . strtolower($hash) . "'"; } $sql .= " AND hash IN (" . implode(',', $hashes) . ")"; } $recordset = $db->Execute($sql); $hashes = array(); $sharekills = array(); while (list($hash, $transfer, $sharekill) = $recordset->FetchRow()) { $hash = strtoupper($hash); $hashes[$hash] = $transfer; $sharekills[$hash] = $sharekill; } //convertTimeText require_once "inc/functions/functions.core.php"; foreach ($tfs as $hash => $t) { if (!isset($hashes[$hash])) { continue; } $transfer = $hashes[$hash]; $sf = new StatFile($transfer); $sf->running = $t['running']; if ($sf->running) { if ($t['eta'] > 0 || $t['eta'] < -1) { $sf->time_left = convertTimeText($t['eta']); } $sf->percent_done = $t['percentDone']; if ($t['status'] != 9 && $t['status'] != 5) { $sf->peers = $t['peers']; //(temp) force creation of pid file to fix first ones file_put_contents($cfg["transfer_file_path"] . '/' . $transfer . ".pid", "rpc"); } if ($t['seeds'] >= 0) { $sf->seeds = $t['seeds']; } if ($t['peers'] >= 0) { $sf->peers = $t['peers']; } if ((double) $t['speedDown'] > 0.0) { $sf->down_speed = formatBytesTokBMBGBTB($t['speedDown']) . "/s"; } if ((double) $t['speedUp'] > 0.0) { $sf->up_speed = formatBytesTokBMBGBTB($t['speedUp']) . "/s"; } if ($t['status'] == 8) { //seeding //$sf->percent_done = 100 + $t['sharing']; $sf->down_speed = ""; } if ($t['status'] == 9) { //seeding queued //$sf->percent_done = 100 + $t['sharing']; $sf->up_speed = ""; $sf->down_speed = ""; } } else { $sf->down_speed = ""; $sf->up_speed = ""; $sf->peers = ""; if ($t['eta'] < -1) { $sf->time_left = 'Done in ' . convertTimeText($t['eta']); } elseif ($sf->percent_done >= 100 && strpos($sf->time_left, 'Done') === false && strpos($sf->time_left, 'Finished') === false) { $sf->time_left = "Done!"; $sf->percent_done = 100; } if ($sf->percent_done < 100 && $sf->percent_done > 0) { //$sf->percent_done = 0 - $sf->percent_done; $sf->stop(); } } $sf->downtotal = $t['downTotal']; $sf->uptotal = $t['upTotal']; if (!$sf->size) { $sf->size = $t['size']; } if ($sf->seeds = -1) { } $sf->seeds = ''; $sf->write(); } //SHAREKILLS foreach ($tfs as $hash => $t) { if (isset($sharekills[$hash])) { if (($t['status'] == 8 || $t['status'] == 9) && $t['sharing'] > $sharekills[$hash]) { $transfer = $hashes[$hash]; if (!$vuze->torrent_stop_tf($hash)) { $msg = "transfer " . $transfer . " does not exist in vuze."; $this->logMessage($msg . "\n", true); AuditAction($cfg["constants"]["debug"], $this->client . "-stop : error {$hash} {$transfer}."); } else { // flag the transfer as stopped (in db) // log AuditAction($cfg["constants"]["stop_transfer"], $this->client . "-stat. : sharekill stopped {$transfer}"); stopTransferSettings($transfer); } } } } }
/** * stop a client * * @param $kill kill-param (optional) * @param $transferPid transfer Pid (optional) */ function _stop($kill = false, $transferPid = 0) { global $cfg; // log AuditAction($cfg["constants"]["stop_transfer"], $this->transfer); // send quit-command to client CommandHandler::add($this->transfer, "q"); CommandHandler::send($this->transfer); // wait until transfer is down waitForTransfer($this->transfer, false, 25); // one more second sleep(1); // flag the transfer as stopped (in db) stopTransferSettings($this->transfer); // set transfers-cache cacheTransfersSet(); // see if the transfer process is hung. $running = $this->runningProcesses(); $isHung = false; foreach ($running as $rng) { $rt = RunningTransfer::getInstance($rng['pinfo'], $this->client); if ($rt->transferFile == $this->transfer) { $isHung = true; AuditAction($cfg["constants"]["error"], "Possible Hung Process for " . $rt->transferFile . " (" . $rt->processId . ")"); } } // kill-request if ($kill && $isHung) { AuditAction($cfg["constants"]["kill_transfer"], $this->transfer); // set pid if (!empty($transferPid)) { // test for valid pid-var if (preg_match('/^[0-9]+$/D', $transferPid)) { $this->pid = $transferPid; } else { $this->state = CLIENTHANDLER_STATE_ERROR; AuditAction($cfg["constants"]["error"], "INVALID PID: " . $transferPid); array_push($this->messages, "INVALID PID: " . $transferPid); return false; } } else { $this->pid = getTransferPid($this->transfer); } // kill it require_once 'inc/defines/defines.signals.php'; if ($this->pid > 0) { $this->callResult = posix_kill($this->pid, SIGKILL); } // try to remove the pid file @unlink($this->transferFilePath . ".pid"); } }
function updateStatFiles($bShowMissing = false) { global $cfg, $db, $client; $rpc = Transmission::getInstance($cfg); // check if running and get all session variables in cache if (!$rpc->session_get()) { echo "unable to connect to transmission-daemon\n"; return; } $tfs = $rpc->torrent_get_tf(); if (empty($tfs)) { echo "no loaded torrents\n"; return; } $sql = "SELECT hash, transfer, sharekill FROM tf_transfers WHERE type='torrent' AND client = 'transmissionrpc'"; $hashes = array("''"); foreach ($tfs as $hash => $t) { $hashes[] = "'" . strtolower($hash) . "'"; } $sql .= " AND hash IN (" . implode(',', $hashes) . ")"; $recordset = $db->Execute($sql); $hashes = array(); $sharekills = array(); while (list($hash, $transfer, $sharekill) = $recordset->FetchRow()) { $hash = strtolower($hash); $hashes[$hash] = $transfer; $sharekills[$hash] = $sharekill; } $max_ul = 1024.0 * $cfg['max_upload_rate']; $max_dl = 1024.0 * $cfg['max_download_rate']; //SHAREKILLS Checks $nbUpdate = 0; foreach ($tfs as $hash => $t) { if (!isset($sharekills[$hash])) { continue; } if (($t['status'] == 8 || $t['status'] == 9) && $t['sharing'] > $sharekills[$hash]) { $transfer = $hashes[$hash]; $nbUpdate++; if (stopTransmissionTransferCron($hash)) { AuditAction($cfg["constants"]["debug"], $client . ": stop error {$transfer}."); } else { AuditAction($cfg["constants"]["stop_transfer"], $this->client . "-stat. : sharekill stopped {$transfer}"); // flag the transfer as stopped (in db) stopTransferSettings($transfer); } } } echo " stopped {$nbUpdate} torrents.\n"; $nbUpdate = 0; $missing = array(); foreach ($tfs as $hash => $t) { if (!isset($hashes[$hash])) { if ($bShowMissing) { $missing[$t['rpcid']] = $t['name']; } continue; } $transfer = $hashes[$hash]; //file_put_contents($cfg["path"].'.Transmission/'."updateStatFiles4.log",serialize($t)); $sf = new StatFile($transfer); $sf->running = $t['running']; if (empty($sf->transferowner)) { $uid = getTransferOwnerID($hash); if ($uid > 0) { $sf->transferowner = GetUsername($uid); echo "transfer '{$transfer}' owner fixed to " . $sf->transferowner . " \n"; $sf->write(); } } if ($sf->running) { $sharebase = (int) $sharekills[$hash]; //$sharekill = (int) round(floatval($t['seedRatioLimit']) * 100); if ($sharebase > 0 && (int) $sf->seedlimit == 0) { AuditAction($cfg["constants"]["debug"], $client . ": changed empty .stat sharekill " . $sf->seedlimit . " to {$sharebase} (from db), {$transfer}."); $sf->seedlimit = $sharebase; } $max_ul = max($t['urate'], $max_ul); $max_dl = max($t['drate'], $max_dl); $max_share = max($sharebase, $sharekill); if ($t['eta'] > 0 || $t['eta'] < -1) { $sf->time_left = convertTimeText($t['eta']); } $sf->percent_done = $t['percentDone']; $sf->sharing = round($t['sharing'], 1); if ($t['status'] != 9 && $t['status'] != 5) { $sf->peers = $t['peers']; $sf->seeds = $t['seeds']; } if ($t['seeds'] >= 0) { $sf->seeds = $t['seeds']; } if ($t['peers'] >= 0) { $sf->peers = $t['peers']; } if ((double) $t['speedDown'] >= 0.0) { $sf->down_speed = formatBytesTokBMBGBTB($t['speedDown']) . "/s"; } if ((double) $t['speedUp'] >= 0.0) { $sf->up_speed = formatBytesTokBMBGBTB($t['speedUp']) . "/s"; } if ($t['status'] == 8) { $sf->percent_done = 100 + $t['sharing']; $sf->down_speed = " "; if (trim($sf->up_speed) == '') { $sf->up_speed = " "; } } if ($t['status'] == 9) { $sf->percent_done = 100 + $t['sharing']; $sf->up_speed = " "; $sf->down_speed = " "; } } else { //Stopped or finished... $sf->down_speed = ""; $sf->up_speed = ""; $sf->peers = ""; $sf->time_left = "0"; if ($t['eta'] < -1) { $sf->time_left = "Done in " . convertTimeText($t['eta']); } elseif ($sf->percent_done >= 100 && strpos($sf->time_left, 'Done') === false && strpos($sf->time_left, 'Finished') === false) { $sf->percent_done = 100; $sf->time_left = "Done!"; } if ($sf->sharing == 0) { $sf->sharing = round($t['sharing'], 1); } if (is_file($cfg["transfer_file_path"] . '/' . $transfer . ".pid")) { unlink($cfg["transfer_file_path"] . '/' . $transfer . ".pid"); } //if ($sf->percent_done < 100 && $sf->percent_done > 0) // $sf->percent_done = 0 - $sf->percent_done; } $sf->downtotal = $t['downTotal']; $sf->uptotal = $t['upTotal']; if ($sf->size == 0) { $sf->size = $t['size']; } if ($sf->seeds = -1) { } $sf->seeds = ''; if ($sf->write()) { $nbUpdate++; } } $nb = count($tfs); echo " updated {$nbUpdate}/{$nb} stat files.\n"; //fix globall sharekill to maximum of torrents sharekill, other torrent with lower sharekill will be stopped by this cron /* if (isset($max_share)) { $sharekill = getTransmissionShareKill(); if ($max_share > $sharekill) { //set vuze global sharekill to max sharekill value $rpc->session_set( array('seedRatioLimit' => round($max_share / 100, 2)) ); if ($cfg['debuglevel'] > 0) { $msg = $client.": changed vuze global sharekill from $sharekill to $max_share."; AuditAction($cfg["constants"]["debug"], $msg); echo $msg."\n"; } } } if ($max_ul > 0) { $vzmaxul = getTransmissionSpeedLimitUpload(); if ($cfg['max_upload_rate'] > 0 && $max_ul > 0) { $max_ul = min($max_ul, 1024.0 * $cfg['max_upload_rate']); } if ($vzmaxul != $max_ul) { $max_ul = $max_ul / 1024; $rpc->session_set( array('speed-limit-up' => $max_ul) ); if ($cfg['debuglevel'] > 0) { $msg = $client.": tranmission global speed-limit-up from $vzmaxul to $max_ul."; AuditAction($cfg["constants"]["debug"], $msg); echo $msg."\n"; } } } */ if ($bShowMissing) { return $missing; } }
function stop($transfer, $kill = false, $transferPid = 0) { global $cfg; $this->_setVarsForTransfer($transfer); AuditAction($cfg["constants"]["debug"], $this->client . "-stop : {$transfer}."); // stop the client $this->_stop($kill, $transferPid); // flag the transfer as stopped (in db) stopTransferSettings($transfer); //@ unlink($this->transferFilePath.".pid"); $stat = new StatFile($this->transfer, $this->owner); return $stat->stop(); }