* @return boolean False if some failure
* @access private
*/
-function glmCheckDatabase ()
+function glmCheckDatabase()
{
global $startupNotices, $config, $wpdb;
// Otherwise, check if we need to update the database
} elseif ($dbVersion != $a['database']['dbCurrentVersion']) {
- // Include an admin message that we're updating the database
- $startupNotices .= '<p>The '.$a['name'].' database tables require updating...</p>';
+ /*
+ * This part of the code checks to see if another instance is doing the database update.
+ * If there is, then it won't be done by this instance and this instance will instead
+ * wait till the database update is done before continuing.
+ *
+ * If there's no other instance doing the update, this instance will try to set and
+ * verify that it is going to do it by setting and verifying a WordPress option.
+ */
- // Traverse version list to find any required updates
- $curVerFound = false;
- $db_setup_status = true;
- foreach($a['database']['dbVersions'] as $version) {
+ $myId = rand();
- $ver = $version['version'];
+ // Try to get any current DB Lock
+ $lockName = GLM_MEMBERS_PLUGIN_DB_LOCK."_".$a['slug'];
+ $lock = get_option($lockName);
- // Find the current version of the database
- if ($ver == $dbVersion) {
- // $startupNotices .= '<p>The database version installed for the '.GLM_MEMBERS_PLUGIN_NAME
- // .' plugin is current and does not require updating.</p>';
- $db_setup_status = true;
- $curVerFound = true;
+ // If another instance is doing a database update
+ // (If we got something back that's a 2 el array that doesn't have my ID and hasn't expired)
+ if ($lock && is_array($lock) && count($lock) == 2 && $lock[0] != $myId && $lock[1] > microtime(true)) {
- // Otherwise if it's already been found and $ver is not the new target version
- } elseif ($curVerFound && $dbVersion != $a['database']['dbCurrentVersion']) {
+ trigger_error("glmCheckDatabase() - Lock Name: $lockName - Instance: $myId - Another instance is updating the database for: ".$a['short_name']."",E_USER_NOTICE);
- // Read in Database creation script
- $sqlFile = $a['database']['dbScriptPath'].'/update_database_V'.$ver.'.sql';
- $sql = file_get_contents($sqlFile);
+ // Unfortunately things get mucked up for other instances, even if we hold them for a bit, so they go here instead.
+ $output = file_get_contents(GLM_MEMBERS_PLUGIN_PATH.'/views/front/error/databaseUpdateInProgress.html');
+ wp_die($output);
- // Replace {prefix} with table name prefix
- $sql = str_replace('{prefix}', $a['database']['dbPrefix'], $sql);
+ } else {
- // Split script into separate queries by looking for lines with only "---"
- $queries = preg_split('/^----$/m', $sql);
+ trigger_error("glmCheckDatabase() - Lock Name: $lockName - Instance: $myId - This instance trying to secure database update lock for: ".$a['short_name'],E_USER_NOTICE);
- // Try executing all queries to update database
- do {
- $q = current($queries);
- $wpdb->query($q);
- $queryError = $wpdb->last_error;
- } while ($queryError == '' && next($queries));
+ // Add our ID and timeout then wait a second
+ add_option($lockName, array($myId, (microtime(true)+GLM_MEMBERS_PLUGIN_DB_LOCK_TIMEOUT)));
+ sleep(1);
- // Check for PHP script to update database
- $phpScript = $a['database']['dbScriptPath'].'/update_database_V'.$ver.'.php';
- if (is_file($phpScript)) {
- require_once $phpScript;
- }
+ // Make sure this instance has the lock
+ $lock = get_option($lockName);
+ if ($lock && is_array($lock) && count($lock) == 2 && $lock[0] == $myId && $lock[1] > microtime(true)) {
- // If there were no errors
- if ($queryError == '') {
- $startupNotices .= '<p>The database for the '.$a['name'].' plugin has been updated '
- .'from V'.$dbVersion.' to V'.$ver.'.</p>';
- } else {
- $startupNotices .= '<p>Failure updating the database tables for the '.$a['name'].' plugin '
- .'from V'.$dbVersion.' to V'.$ver.'.</p>';
- $db_setup_status = false;
- $startupNotices .= '<p>Database Update Error:</b> '.$queryError.'</p>';
- }
+ /*
+ * At this point this instance should have a verified lock on doing the database
+ * update and all other instances should be waiting for this to complete.
+ */
- $dbVersion = $ver;
- $db_setup_status = true;
+ trigger_error("glmCheckDatabase() - Lock Name: $lockName - Instance: $myId - This instance has a verified database update lock for: ".$a['short_name'],E_USER_NOTICE);
- }
+ // Include an admin message that we're updating the database
+ $startupNotices .= '<p>The '.$a['name'].' database tables require updating...</p>';
- // Save the new version. If we've had a problem updating the database, then stop here.
- if ($db_setup_status) {
+ // Traverse version list to find any required updates
+ $curVerFound = false;
+ $db_setup_status = true;
+ foreach($a['database']['dbVersions'] as $version) {
+
+ $ver = $version['version'];
+
+ // Find the current version of the database
+ if ($ver == $dbVersion) {
+
+ $db_setup_status = true;
+ $curVerFound = true;
+
+ // Otherwise if it's already been found and $ver is not the new target version
+ } elseif ($curVerFound && $dbVersion != $a['database']['dbCurrentVersion']) {
+
+ // Read in Database creation script
+ $sqlFile = $a['database']['dbScriptPath'].'/update_database_V'.$ver.'.sql';
+ $sql = file_get_contents($sqlFile);
+
+ // Replace {prefix} with table name prefix
+ $sql = str_replace('{prefix}', $a['database']['dbPrefix'], $sql);
+
+ // Split script into separate queries by looking for lines with only "---"
+ $queries = preg_split('/^----$/m', $sql);
+
+ // Try executing all queries to update database
+ do {
+ $q = current($queries);
+ $wpdb->query($q);
+ $queryError = $wpdb->last_error;
+ } while ($queryError == '' && next($queries));
+
+ // Check for PHP script to update database
+ $phpScript = $a['database']['dbScriptPath'].'/update_database_V'.$ver.'.php';
+ if (is_file($phpScript)) {
+ require_once $phpScript;
+ }
+
+ // If there were no errors
+ if ($queryError == '') {
+ $startupNotices .= '<p>The database for the '.$a['name'].' plugin has been updated '
+ .'from V'.$dbVersion.' to V'.$ver.'.</p>';
+ } else {
+ $startupNotices .= '<p>Failure updating the database tables for the '.$a['name'].' plugin '
+ .'from V'.$dbVersion.' to V'.$ver.'.</p>';
+ $db_setup_status = false;
+ $startupNotices .= '<p>Database Update Error:</b> '.$queryError.'</p>';
+ }
+
+ $dbVersion = $ver;
+ $db_setup_status = true;
+
+ }
+
+ // Save the new version.
+ if ($db_setup_status) {
+ update_option($a['database']['dbActiveVersionOption'], $dbVersion);
+ } else {
+ // There was a problem updating the database, so don't do any more.
+ break;
+ }
- // Save the version of the installed database
- update_option($a['database']['dbActiveVersionOption'], $dbVersion);
+ }
- } else {
- break;
- }
+ if ($db_setup_status) {
+ trigger_error("glmCheckDatabase() - Lock Name: $lockName - Instance: $myId - This instance has updated the database for: ".$a['short_name'],E_USER_NOTICE);
+ $startupNotices .= '<p><b>Database tables updated.</b></p>';
+ } else {
+ trigger_error("glmCheckDatabase() - Lock Name: $lockName - Instance: $myId - This instance had a problem updating the database for: ".$a['short_name'],E_USER_NOTICE);
+ }
- }
+ /*
+ * This instance has completed the database update (or failed) and will remove
+ * the WordPress option that's locking out the other instances so they can
+ * continue.
+ *
+ * If there was a failure doing the update, this plugin will be deactivated
+ * at the bottom of this function.
+ */
+
+ // Remove our lock
+ delete_option($lockName);
- if ($db_setup_status) {
+ trigger_error("glmCheckDatabase() - Lock Name: $lockName - Instance: $myId - This instance has removed database update lock for: ".$a['short_name'],E_USER_NOTICE);
- $startupNotices .= '<p><b>Database tables updated.</b></p>';
+ }
}
} else {
// Deactivate this add-on
include_once ABSPATH . 'wp-admin/includes/plugin.php';
deactivate_plugins($a['slug'].'/index.php');
- $startupNotices .= '<p>Plugin '.$a['name'].' Deactivated.</p>';
+ $startupNotices .= '<p>Plugin '.$a['name'].' Deactivated due to serious database update problem.</p>';
}
} // For each plugin