Browse files

Command line interface to running slow/major ThinkUp database migrations

Closes #444, closes #571
  • Loading branch information...
1 parent 4bd27eb commit 9f6f8da32d74fc39db6518874f7a8818aabc9ba3 Mark Wilkie committed with ginatrapani Jan 21, 2011
View
17 tests/TestOfBackupController.php
@@ -34,6 +34,7 @@ class TestOfBackupController extends ThinkUpUnitTestCase {
public function setUp() {
parent::setUp();
new BackupMySQLDAO();
+ $this->config = Config::getInstance();
$this->pdo = BackupMySQLDAO::$PDO;
$this->backup_file = THINKUP_WEBAPP_PATH . BackupDAO::CACHE_DIR . '/thinkup_db_backup.zip';
$this->backup_test = THINKUP_WEBAPP_PATH . BackupDAO::CACHE_DIR . '/thinkup_db_backup_test.zip';
@@ -85,6 +86,22 @@ public function testLoadBackupView() {
$this->assertPattern('/Back Up Your ThinkUp Data/', $results);
}
+ public function XtestBackupCrawlerHasMutex() {
+ // mutex needs to be on another db handle, so can't use doa framework to test to test
+ $mutex_name = $this->config->getValue('db_name') . '.' . 'crawler';
+ $result = $this->db->exec("SELECT GET_LOCK('$mutex_name', 1)");
+ var_dump(mysql_fetch_assoc($result));
+ $this->simulateLogin('me@example.com', true);
+ $controller = new BackupController(true);
+ $_GET['backup'] = 'true';
+ ob_start();
+ $controller->go();
+ $results = ob_get_contents();
+ ob_end_clean();
+ echo $results;
+ $this->db->exec("SELECT RELEASE_LOCK('$mutex_name')");
+ }
+
public function testBackup() {
$this->simulateLogin('me@example.com', true);
$controller = new BackupController(true);
View
24 webapp/_lib/controller/class.BackupController.php
@@ -43,6 +43,7 @@ public function adminControl() {
try {
$backup_dao = DAOFactory::getDAO('BackupDAO');
if(isset($_GET['backup'])) {
+ self::mutexLock();
/* export/download backup file */
$backup_dao->export();
if( ! headers_sent() ) { // this is so our test don't barf on us
@@ -63,7 +64,9 @@ public function adminControl() {
} else {
throw new Exception("Unable to read backup zip file: " + $this->backup_file);
}
+ self::mutexLock(true);
} else if(isset($_FILES['backup_file'])) {
+ self::mutexLock();
/* upload backup file */
if($_FILES['backup_file']['error']) {
if($_FILES['backup_file']['error'] == UPLOAD_ERR_INI_SIZE) {
@@ -79,7 +82,7 @@ public function adminControl() {
$this->addSuccessMessage("Data Import Successfull!");
return $this->generateView();
}
-
+ self::mutexLock(true);
} else {
/* load default form */
return $this->generateView();
@@ -89,4 +92,23 @@ public function adminControl() {
return $this->generateView();
}
}
+
+ /**
+ *
+ * @param boolean $release, if defined release mutex, else get it
+ * @throws CrawlerLockedException if unable to get crawler mutex
+ */
+ public static function mutexLock($release = false) {
+ $mutex_dao = DAOFactory::getDAO('MutexDAO');
+ $global_mutex_name = Crawler::GLOBAL_MUTEX;
+ if($release) {
+ $mutex_dao->releaseMutex($global_mutex_name);
+ } else {
+ // Everyone needs to check the global mutex
+ $lock_successful = $mutex_dao->getMutex($global_mutex_name);
+ if (! $lock_successful) {
+ throw new CrawlerLockedException("A crawl is in progress, please wait until completed...");
+ }
+ }
+ }
}
View
4 webapp/_lib/controller/class.UpgradeController.php
@@ -71,7 +71,9 @@ class UpgradeController extends ThinkUpAuthController {
* @return UpgradeController
*/
public function __construct($session_started=false) {
- parent::__construct($session_started);
+ if(! getenv('CLI_BACKUP')) {
+ parent::__construct($session_started);
+ }
}
public function authControl() {
View
9 webapp/_lib/model/class.Crawler.php
@@ -31,6 +31,13 @@
*
*/
class Crawler extends PluginHook {
+
+ /**
+ *
+ * @var Crawler
+ */
+ const GLOBAL_MUTEX = 'crawler';
+
/**
*
* @var Crawler
@@ -82,7 +89,7 @@ public function crawl() {
throw new InstallerException("ThinkUp needs a database migration, so we are unable to run the crawler.");
}
- $global_mutex_name = 'crawler';
+ $global_mutex_name = self::GLOBAL_MUTEX;
// Everyone needs to check the global mutex
$lock_successful = $mutex_dao->getMutex($global_mutex_name);
View
7 webapp/install/cli/backup.php
@@ -51,6 +51,9 @@
usage();
} else {
+ // set global mutex
+ BackupController::mutexLock();
+
putenv('BACKUP_VERBOSE=true');
$backup_dao = DAOFactory::getDAO('BackupDAO');
if($argv[0] == '--export') {
@@ -67,6 +70,10 @@
print "\nImport completed...\n\n";
}
+
+ // release global mutex
+ BackupController::mutexLock(true);
+
}
}
} catch(Exception $e) {
View
127 webapp/install/cli/upgrade.php
@@ -0,0 +1,127 @@
+<?php
+/**
+ *
+ * ThinkUp/webapp/install/cli/upgrade.php
+ *
+ * Copyright (c) 2009-2010 Mark Wilkie
+ *
+ * LICENSE:
+ *
+ * This file is part of ThinkUp (http://thinkupapp.com).
+ *
+ * ThinkUp is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any
+ * later version.
+ *
+ * ThinkUp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with ThinkUp. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *
+ * Command line interface for upgrading up thinkup/data
+ *
+ * @license http://www.gnu.org/licenses/gpl.html
+ * @copyright 2009-2010 Mark Wilkie
+ * @author Mark Wilkie <mwilkie[at]gmail[dot]com>
+ */
+chdir('../..');
+require_once 'init.php';
+
+// don't run via the web...
+if(isset($_SERVER['SERVER_NAME'])) {
+ die("This script should only be run via the command line...");
+}
+
+// help?
+array_shift($argv);
+if($argv[0] && preg_match('/^(\-h|\-\-help)$/i', $argv[0])) {
+ usage();
+}
+
+try {
+
+ // do we need a migration?
+ $db_version = UpgradeController::getCurrentDBVersion($cached = false);
+ $config = Config::getInstance();
+ $thinkup_db_version = $config->getValue('THINKUP_VERSION');
+ $filename = false;
+ if($db_version == $thinkup_db_version) {
+ error_log("\nYour system is up to date...\n");
+ exit;
+ } else {
+ print "\nThinkup needs to be upgraded to version $thinkup_db_version, proceed => [y|n] ";
+ $handle = fopen ("php://stdin","r");
+ $line = fgets($handle);
+ if(trim($line) != 'y'){
+ exit;
+ }
+ print "\nWould you like to backup your data first? => [y|n] ";
+ $handle = fopen ("php://stdin","r");
+ $line = fgets($handle);
+ if(trim($line) == 'y'){
+ print "\nEnter a .zip filename (/path/tp/backup.zip) => ";
+ $handle = fopen ("php://stdin","r");
+ $line = fgets($handle);
+ $filename = trim($line);
+ }
+ }
+
+
+ // set global mutex
+ BackupController::mutexLock();
+
+ // run backup first?
+ if($argv[0] && preg_match('/^(\-h|\-\-help)$/i', $argv[0])) {
+ usage();
+ } else if($filename) {
+ if( ! preg_match('/\.zip$/', $filename) ) {
+ error_log("\nError: data file should end in .zip");
+ usage();
+ } else {
+ putenv('BACKUP_VERBOSE=true');
+ $backup_dao = DAOFactory::getDAO('BackupDAO');
+ print "\nExporting data to: $filename\n\n";
+ $backup_dao->export($filename);
+ print "\nBackup completed...\n\n";
+ }
+ }
+
+ // run updates...
+
+ // get migrations we need to run...
+ print "\nUpgrading Thinkup to version $thinkup_db_version...\n\n";
+ putenv('CLI_BACKUP=true');
+ $upgrade_ctl = new UpgradeController();
+ $migrations = $upgrade_ctl->getMigrationList($db_version);
+ $install_dao = DAOFactory::getDAO('InstallerDAO');
+ foreach($migrations as $migration) {
+ print(" Running migration " . $migration['version'] . "\n");
+ $install_dao->runMigrationSQL($migration['sql']);
+ }
+
+ $option_dao = DAOFactory::getDAO('OptionDAO');
+ $option = $option_dao->getOptionByName(OptionDAO::APP_OPTIONS, 'database_version');
+ if($option) {
+ $option_dao->updateOptionByName(OptionDAO::APP_OPTIONS, 'database_version',$thinkup_db_version);
+ } else {
+ $option_dao->insertOption(OptionDAO::APP_OPTIONS, 'database_version', $thinkup_db_version);
+ }
+
+ // release global mutex
+ BackupController::mutexLock();
+
+ print "\nUpgrade complete...\n\n";
+
+} catch(Exception $e) {
+ error_log(" Error: " . $e->getMessage() . "\n");
+}
+
+function usage() {
+ print "\n Usage:\n\n";
+ print " php update.php [--help]\n\n";
+ print " --help - usage help\n\n";
+ exit;
+}

0 comments on commit 9f6f8da

Please sign in to comment.