cs-webdbupgrade-commits Mailing List for CS Web DB Upgrade
Status: Inactive
Brought to you by:
crazedsanity
You can subscribe to this list here.
2009 |
Jan
(7) |
Feb
|
Mar
|
Apr
|
May
|
Jun
(2) |
Jul
(13) |
Aug
(18) |
Sep
|
Oct
|
Nov
|
Dec
|
---|
From: <cra...@us...> - 2009-08-13 15:09:32
|
Revision: 40 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=40&view=rev Author: crazedsanity Date: 2009-08-13 15:09:23 +0000 (Thu, 13 Aug 2009) Log Message: ----------- Re-apply changes from the trunk/0.1 folder that were for the trunk/0.2 folder. Modified Paths: -------------- trunk/0.2/cs_webdbupgrade.class.php Modified: trunk/0.2/cs_webdbupgrade.class.php =================================================================== --- trunk/0.2/cs_webdbupgrade.class.php 2009-08-13 15:04:14 UTC (rev 39) +++ trunk/0.2/cs_webdbupgrade.class.php 2009-08-13 15:09:23 UTC (rev 40) @@ -13,6 +13,7 @@ */ require_once(constant('LIBDIR') .'/cs-versionparse/cs_version.abstract.class.php'); +require_once(constant('LIBDIR') .'/cs_debug.php'); class cs_webdbupgrade extends cs_versionAbstract { @@ -46,9 +47,16 @@ /** Name (absolute location) of *.lock file that indicates an upgrade is running. */ private $lockfile; + /** Determines if an internal upgrade is happening (avoids some infinite loops) */ + private $internalUpgradeInProgress = false; + /** */ private $allowNoDBVersion=true; + /** Log messages to store during an internal upgrade (to avoid problems) */ + private $storedLogs = array(); + private $debugLogs=array(); + /** List of acceptable suffixes; example "1.0.0-BETA3" -- NOTE: these MUST be in * an order that reflects newest -> oldest; "ALPHA happens before BETA, etc. */ private $suffixList = array( @@ -58,34 +66,17 @@ ); //========================================================================= - public function __construct($versionFileLocation, array $config) { + public function __construct($versionFileLocation, $upgradeConfigFile, $lockFile='upgrade.lock') { - //Handle the config array (cope with XML-ish array) - if(is_array($config)) { - //check if it is in the complex XML array style... - $keys = array_keys($config); - if(isset($config[$keys[0]]['type'])) { - $this->fix_xml_config($config); - $this->config = $this->tempXmlConfig; - } - else { - $this->config = $config; - } - } - else { - throw new exception(__METHOD__ .": no configuration available"); - } - - //cope with problems in CS-Content v1.0-ALPHA9 (or before)--see http://project.crazedsanity.com/extern/helpdesk/view?ID=281 - if(isset($this->config['DBPARMLINKER'])) { - $this->config['DBPARAMS'] = array(); - foreach($this->config['DBPARMLINKER'] as $i=>$loc) { - $this->config['DBPARAMS'][strtolower($i)] = $this->config[$loc]; - unset($this->config[$loc]); - } - unset($this->config['DBPARMLINKER']); - } - + //setup configuration parameters for database connectivity. + $dbParams = array( + 'host' => constant(__CLASS__ .'-DB_CONNECT_HOST'), + 'port' => constant(__CLASS__ .'-DB_CONNECT_PORT'), + 'dbname' => constant(__CLASS__ .'-DB_CONNECT_DBNAME'), + 'user' => constant(__CLASS__ .'-DB_CONNECT_USER'), + 'password' => constant(__CLASS__ .'-DB_CONNECT_PASSWORD') + ); + $this->config['DBPARAMS'] = $dbParams; //Check for some required constants. $requisiteConstants = array('LIBDIR'); if(!defined('LIBDIR')) { @@ -103,32 +94,46 @@ require_once(constant('LIBDIR') .'/cs-phpxml/cs_phpxmlCreator.class.php'); require_once(constant('LIBDIR') .'/cs-phpxml/cs_arrayToPath.class.php'); - $this->versionFileLocation = $versionFileLocation; - $this->fsObj = new cs_fileSystem(constant('SITE_ROOT')); $this->gfObj = new cs_globalFunctions; if(defined('DEBUGPRINTOPT')) { $this->gfObj->debugPrintOpt = constant('DEBUGPRINTOPT'); } - if(!isset($this->config['DB_PRIMARYKEY']) || !isset($this->config['DB_TABLE'])) { + if(!defined(__CLASS__ .'-DB_PRIMARYKEY') || !defined(__CLASS__ .'-DB_TABLE')) { throw new exception(__METHOD__ .": no setting for DB_TABLE or DB_PRIMARYKEY, cannot continue"); } + else { + $this->config['DB_TABLE'] = constant(__CLASS__ .'-DB_TABLE'); + $this->config['DB_PRIMARYKEY'] = constant(__CLASS__ .'-DB_PRIMARYKEY'); + } $this->sequenceName = $this->config['DB_TABLE'] .'_'. $this->config['DB_PRIMARYKEY'] .'_seq'; if(!defined('DBTYPE')) { throw new exception(__METHOD__ .": required constant 'DBTYPE' not set"); } - if(!isset($this->config['CONFIG_FILE_LOCATION'])) { - throw new exception(__METHOD__ .": required setting 'CONFIG_FILE_LOCATION' not found"); + + if(!file_exists($upgradeConfigFile) || !is_readable($upgradeConfigFile)) { + throw new exception(__METHOD__ .": required upgrade config file location (". $upgradeConfigFile .") not set or unreadable"); } + else { + $this->config['UPGRADE_CONFIG_FILE'] = $upgradeConfigFile; + } if(!strlen($versionFileLocation) || !file_exists($versionFileLocation)) { throw new exception(__METHOD__ .": unable to locate version file (". $versionFileLocation .")"); } - if(!isset($this->config['RWDIR']) || !is_dir($this->config['RWDIR']) || !is_readable($this->config['RWDIR']) || !is_writable($this->config['RWDIR'])) { - throw new exception(__METHOD__ .": missing RWDIR (". $this->config['RWDIR'] .") or isn't readable/writable"); + $this->set_version_file_location($versionFileLocation); + + if(!defined(__CLASS__ .'-RWDIR') || !is_dir(constant(__CLASS__ .'-RWDIR')) || !is_readable(constant(__CLASS__ .'-RWDIR')) || !is_writable(constant(__CLASS__ .'-RWDIR'))) { + throw new exception(__METHOD__ .": missing RWDIR (". constant(__CLASS__ .'-RWDIR') .") or isn't readable/writable"); } - $this->lockfile = $this->config['RWDIR'] .'/upgrade.lock'; + else { + $this->config['RWDIR'] = constant(__CLASS__ .'-RWDIR'); + } + if(is_null($lockFile) || !strlen($lockFile)) { + $lockFile = 'upgrade.lock'; + } + $this->lockfile = $this->config['RWDIR'] .'/'. $lockFile; $this->db = new cs_phpDB(constant('DBTYPE')); try { @@ -140,12 +145,15 @@ if($this->check_lockfile()) { //there is an existing lockfile... - $this->error_handler(__METHOD__ .": upgrade in progress: ". $this->fsObj->read($this->lockfile)); + throw new exception(__METHOD__ .": upgrade in progress: ". $this->fsObj->read($this->lockfile)); } $this->check_internal_upgrades(); - try { - $this->connect_logger("Upgrade"); + + try { + $loggerDb = new cs_phpDB(constant('DBTYPE')); + $loggerDb->connect($this->config['DBPARAMS'], true); + $this->logsObj = new cs_webdblogger($loggerDb, "Upgrade ". $this->projectName, false); } catch(exception $e) { throw new exception(__METHOD__ .": failed to create logger::: ". $e->getMessage()); @@ -167,17 +175,12 @@ $this->config['UPGRADE_CONFIG_FILE'] = dirname(__FILE__) .'/upgrades/upgrade.xml'; - //connect the logger... - try { - $this->connect_logger("Internal Upgrade"); - } - catch(exception $e) { - $this->error_handler($e->getMessage()); - } + //set a status flag so we can store log messages (for now). + $this->internalUpgradeInProgress = true; //do stuff here... - $this->versionFileLocation = dirname(__FILE__) .'/VERSION'; + $this->set_version_file_location(dirname(__FILE__) .'/VERSION'); $this->read_version_file(); //if there is an error, then... uh... yeah. @@ -185,7 +188,7 @@ $this->get_database_version(); } catch(exception $e) { - #throw new exception(__METHOD__ .": error while retrieving database version: ". $e->getMessage()); + throw new exception(__METHOD__ .": error while retrieving database version: ". $e->getMessage()); //try creating the version. $this->load_initial_version(); @@ -193,12 +196,13 @@ //do upgrades here... $this->check_versions(true); + $this->internalUpgradeInProgress = false; //reset internal vars. - $this->versionFileLocation = $oldVersionFileLocation; + $this->set_version_file_location($oldVersionFileLocation); $this->config['UPGRADE_CONFIG_FILE'] = $oldUpgradeConfigFile; $this->read_version_file(); @@ -223,7 +227,7 @@ //check to see if the lock files for upgrading exist. if($this->upgrade_in_progress()) { - $this->logsObj->log_by_class("Upgrade in progress", 'notice'); + $this->do_log("Upgrade in progress", 'notice'); throw new exception(__METHOD__ .": upgrade in progress"); } else { @@ -325,6 +329,7 @@ //========================================================================= private function perform_upgrade() { + $this->logsObj->suspendLogging=true; //make sure there's not already a lockfile. if($this->upgrade_in_progress()) { //ew. Can't upgrade. @@ -334,7 +339,7 @@ $lockConfig = $this->upgrade_in_progress(TRUE); $this->fsObj->cd("/"); - $this->logsObj->log_by_class("Starting upgrade process...", 'begin'); + $this->do_log("Starting upgrade process...", 'begin'); //TODO: not only should the "create_file()" method be run, but also do a sanity check by calling lock_file_exists(). if($lockConfig === 0) { @@ -342,7 +347,7 @@ $this->error_handler(__METHOD__ .": failed to set 'upgrade in progress'"); } else { - $this->logsObj->log_by_class(__METHOD__ .": result of creating lockfile: (". $lockConfig .")", 'debug'); + $this->do_log(__METHOD__ .": result of creating lockfile: (". $lockConfig .")", 'debug'); //push data into our internal "config" array. $this->read_upgrade_config_file(); @@ -353,39 +358,38 @@ if($versionConflictInfo !== false) { - $this->logsObj->log_by_class("Upgrading ". $versionConflictInfo ." versions, from " . + $this->do_log("Upgrading ". $versionConflictInfo ." versions, from " . "(". $this->databaseVersion .") to (". $this->versionFileVersion .")", 'info'); } $upgradeList = $this->get_upgrade_list(); - try { $i=0; - $this->logsObj->log_by_class(__METHOD__ .": starting to run through the upgrade list, starting at (". $this->databaseVersion ."), " . + $this->do_log(__METHOD__ .": starting to run through the upgrade list, starting at (". $this->databaseVersion ."), " . "total number of upgrades to perform: ". count($upgradeList), 'debug'); $this->db->beginTrans(__METHOD__); foreach($upgradeList as $fromVersion=>$toVersion) { $details = __METHOD__ .": upgrading from ". $fromVersion ." to ". $toVersion ."... "; - $this->logsObj->log_by_class($details, 'system'); + $this->do_log($details, 'system'); $this->do_single_upgrade($fromVersion, $toVersion); $this->get_database_version(); $i++; $details = __METHOD__ .": finished upgrade #". $i .", now at version (". $this->databaseVersion .")"; - $this->logsObj->log_by_class($details, 'system'); + $this->do_log($details, 'system'); } if($i < count($upgradeList)) { - $this->logsObj->log_by_class(__METHOD__ .": completed upgrade ". $i ." of ". count($upgradeList), 'debug'); + $this->do_log(__METHOD__ .": completed upgrade ". $i ." of ". count($upgradeList), 'debug'); } else { if($this->databaseVersion == $this->versionFileVersion) { - $this->logsObj->log_by_class(__METHOD__ .": finished upgrading after performing (". $i .") upgrades", 'debug'); + $this->do_log(__METHOD__ .": finished upgrading after performing (". $i .") upgrades", 'debug'); $this->newVersion = $this->databaseVersion; } else { - $this->logsObj->log_by_class(__METHOD__ .": upgradeList::: ". $this->gfObj->debug_print($upgradeList,0), 'debug'); + $this->do_log(__METHOD__ .": upgradeList::: ". $this->gfObj->debug_print($upgradeList,0), 'debug'); $this->error_handler(__METHOD__ .": finished upgrade, but version wasn't updated (expecting '". $this->versionFileVersion ."', got '". $this->databaseVersion ."')!!!"); } } @@ -394,12 +398,16 @@ $this->db->commitTrans(); } catch(exception $e) { - $this->error_handler(__METHOD__ .": upgrade aborted:::". $e->getMessage()); + $transactionStatus = $this->db->get_transaction_status(false); + $this->error_handler(__METHOD__ .": transaction status=(". $transactionStatus ."), upgrade aborted:::". $e->getMessage()); $this->db->rollbackTrans(); } - $this->logsObj->log_by_class("Upgrade process complete", 'end'); + $this->logsObj->suspendLogging=false; + $this->do_log("Upgrade process complete", 'end'); } } + $this->logsObj->suspendLogging=false; + $logsHandled = $this->logsObj->handle_suspended_logs(); }//end perform_upgrade() //========================================================================= @@ -607,7 +615,7 @@ $this->error_handler(__METHOD__ .": target version not specified, unable to proceed with upgrade for ". $versionIndex); } } - $this->logsObj->log_by_class("Finished upgrade to ". $this->newVersion, 'system'); + $this->do_log("Finished upgrade to ". $this->newVersion, 'system'); }//end do_single_upgrade() //========================================================================= @@ -666,7 +674,7 @@ } if(!$retval) { - $this->logsObj->log_by_class("Version check failed, versionString=(". $versionString ."), checkVersion=(". $this->newVersion .")", 'FATAL'); + $this->do_log("Version check failed, versionString=(". $versionString ."), checkVersion=(". $this->newVersion .")", 'FATAL'); } } @@ -684,20 +692,16 @@ private function do_scripted_upgrade(array $upgradeData) { $myConfigFile = $upgradeData['SCRIPT_NAME']; - $this->logsObj->log_by_class("Preparing to run script '". $myConfigFile ."'", 'debug'); + $this->do_log("Preparing to run script '". $myConfigFile ."'", 'debug'); //we've got the filename, see if it exists. - if(isset($this->config['UPGRADE_SCRIPTS_DIR'])) { - $scriptsDir = $this->config['UPGRADE_SCRIPTS_DIR']; - } - else { - $this->logsObj->log_by_class("No UPGRADE_SCRIPTS_DIR config setting", 'warning'); - $scriptsDir = dirname($this->config['UPGRADE_CONFIG_FILE']); - } + + $scriptsDir = dirname($this->config['UPGRADE_CONFIG_FILE']); $fileName = $scriptsDir .'/'. $myConfigFile; + if(file_exists($fileName)) { - - $this->logsObj->log_by_class("Performing scripted upgrade (". $myConfigFile .")", 'DEBUG'); + + $this->do_log("(". __CLASS__ .") Performing scripted upgrade (". $myConfigFile .") from file '". $fileName ."'", 'DEBUG'); $createClassName = $upgradeData['CLASS_NAME']; $classUpgradeMethod = $upgradeData['CALL_METHOD']; require_once($fileName); @@ -710,12 +714,12 @@ if($upgradeResult === true) { //yay, it worked! - $this->logsObj->log_by_class("Upgrade succeeded (". $upgradeResult .")", 'success'); + $this->do_log("Upgrade succeeded (". $upgradeResult .")", 'success'); } else { $this->error_handler(__METHOD__ .": upgrade failed (". $upgradeResult .")"); } - $this->logsObj->log_by_class("Finished running ". $createClassName ."::". $classUpgradeMethod ."(), result was (". $upgradeResult .")", 'debug'); + $this->do_log("Finished running ". $createClassName ."::". $classUpgradeMethod ."(), result was (". $upgradeResult .")", 'debug'); } else { $this->error_handler(__METHOD__ .": upgrade method doesn't exist (". $createClassName ."::". $classUpgradeMethod @@ -788,11 +792,11 @@ $retval[$matchVersion] = $data['TARGET_VERSION']; } else { - $this->logsObj->log_by_class(__METHOD__ .": entry in upgrade.xml (". $matchVersion .") is higher than the VERSION file (". $this->versionFileVersion .")", 'warning'); + $this->do_log(__METHOD__ .": entry in upgrade.xml (". $matchVersion .") is higher than the VERSION file (". $this->versionFileVersion .")", 'warning'); } } else { - $this->logsObj->log_by_class(__METHOD__ .": SKIPPING (". $matchVersion .")", 'debug'); + $this->do_log(__METHOD__ .": SKIPPING (". $matchVersion .")", 'debug'); } } @@ -802,7 +806,7 @@ } else { //no intermediary upgrades: just pass back the latest version. - $this->logsObj->log_by_class(__METHOD__ .": no intermediary upgrades", 'debug'); + $this->do_log(__METHOD__ .": no intermediary upgrades", 'debug'); $retval[$dbVersion] = $this->versionFileVersion; } @@ -856,7 +860,7 @@ $a2p = new cs_arrayToPath($config); } catch(exception $e) { - $this->logsObj->log_by_class(__METHOD__ .': encountered exception: '. $e->getMessage()); + $this->do_log(__METHOD__ .': encountered exception: '. $e->getMessage()); $this->error_handler($e->getMessage()); } if(!is_array($this->tempXmlConfig)) { @@ -866,7 +870,7 @@ $myA2p = new cs_arrayToPath(&$this->tempXmlConfig); } catch(exception $e) { - $this->logsObj->log_by_class(__METHOD__ .': encountered exception: '. $e->getMessage()); + $this->do_log(__METHOD__ .': encountered exception: '. $e->getMessage()); $this->error_handler($e->getMessage()); } @@ -930,7 +934,7 @@ $logRes = 'Failed to load'; $logType = 'error'; } - $this->logsObj->log_by_class($logRes .' table ('. $this->config['DB_TABLE'] .') into ' . + $this->do_log($logRes .' table ('. $this->config['DB_TABLE'] .') into ' . 'database::: '. $loadTableResult, $logType); return($loadTableResult); @@ -1026,7 +1030,12 @@ //========================================================================= public function error_handler($details) { //log the error. - $this->logsObj->log_by_class($details, 'exception in code'); + if(!is_object($this->logsObj)) { + throw new exception(__METHOD__ .": error while running an internal upgrade::: ". $details); + } + if($this->internalUpgradeInProgress === false) { + $this->do_log($details, 'exception in code'); + } //now throw an exception so other code can catch it. throw new exception($details); @@ -1039,19 +1048,24 @@ public function load_initial_version() { //if there's an INITIAL_VERSION in the upgrade config file, use that. $this->read_upgrade_config_file(); + $insertData = array(); if(isset($this->config['UPGRADELIST']['INITIALVERSION'])) { - $insertData = $this->parse_version_string($this->config['UPGRADELIST']['INITIALVERSION']); + $parseThis = $this->config['UPGRADELIST']['INITIALVERSION']; } else { - $insertData = $this->parse_version_string($this->versionFileVersion); + $parseThis = $this->versionFileVersion; } - $insertData['project_name'] = $this->projectName; + $versionInfo = $this->parse_version_string($parseThis); + $insertData = array( + 'project_name' => $this->projectName, + 'version_string' => $versionInfo['version_string'] + ); $sql = 'INSERT INTO '. $this->config['DB_TABLE'] . $this->gfObj->string_from_array($insertData, 'insert'); if($this->db->run_insert($sql, $this->sequenceName)) { $loadRes = true; - $this->logsObj->log_by_class("Created data for '". $this->projectName ."' with version '". $insertData['version_string'] ."'", 'initialize'); + $this->do_log("Created data for '". $this->projectName ."' with version '". $insertData['version_string'] ."'", 'initialize'); } else { $this->error_handler(__METHOD__ .": failed to load initial version::: ". $e->getMessage()); @@ -1064,11 +1078,15 @@ //========================================================================= - private function connect_logger($logCategory) { - $loggerDb = new cs_phpDB(constant('DBTYPE')); - $loggerDb->connect($this->config['DBPARAMS'], true); - $this->logsObj = new cs_webdblogger($loggerDb, $logCategory); - }//end connect_logger() + protected function do_log($message, $type) { + $this->debugLogs[] = array('project'=>$this->projectName,'upgradeFile'=>$this->config['UPGRADE_CONFIG_FILE'],'message'=>$message,'type'=>$type); + if($this->internalUpgradeInProgress === true) { + $this->storedLogs[] = func_get_args(); + } + else { + $this->logsObj->log_by_class($message, $type); + } + }//end do_log() //========================================================================= This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-08-13 15:04:25
|
Revision: 39 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=39&view=rev Author: crazedsanity Date: 2009-08-13 15:04:14 +0000 (Thu, 13 Aug 2009) Log Message: ----------- Revert back to the last change that didn't have anything to do with v0.2.x Modified Paths: -------------- trunk/0.1/VERSION trunk/0.1/cs_webdbupgrade.class.php trunk/0.1/schema/schema.sql Added Paths: ----------- trunk/0.1/CREDITS trunk/0.1/LICENSE trunk/0.1/README.txt trunk/0.1/exampleUpgrades/ trunk/0.1/exampleUpgrades/upgrade.xml trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA4.php trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA7.php Removed Paths: ------------- trunk/0.1/docs/ trunk/0.1/exampleUpgrades/upgrade.xml trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA4.php trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA7.php trunk/0.1/upgrades/ Copied: trunk/0.1/CREDITS (from rev 28, trunk/0.1/CREDITS) =================================================================== --- trunk/0.1/CREDITS (rev 0) +++ trunk/0.1/CREDITS 2009-08-13 15:04:14 UTC (rev 39) @@ -0,0 +1,3 @@ + +Lead Developer: Dan Falconer (cra...@us...) + Copied: trunk/0.1/LICENSE (from rev 28, trunk/0.1/LICENSE) =================================================================== --- trunk/0.1/LICENSE (rev 0) +++ trunk/0.1/LICENSE 2009-08-13 15:04:14 UTC (rev 39) @@ -0,0 +1,291 @@ +NOTE: a full HTML version of this license can be found at: +http://www.opensource.org/licenses/gpl-license.php + +It has been reproduced below without any HTML. +========================================================================== + +The GNU General Public License (GPL) + +Version 2, June 1991 + + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + +NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS Copied: trunk/0.1/README.txt (from rev 28, trunk/0.1/README.txt) =================================================================== --- trunk/0.1/README.txt (rev 0) +++ trunk/0.1/README.txt 2009-08-13 15:04:14 UTC (rev 39) @@ -0,0 +1,60 @@ + +$Id$ + +This system is built to make upgrading a database-driven app seamless. No need +to coordinate SQL or schema changes with the code updates: previously, one would +have to take the entire website down, run the schema/SQL change, update the code, +and (if you're lucky) check a "test" website to ensure it works before unleashing +it upon your users.... if you're unlucky, they both must be run in unison, and +if the SQL or schema change fails, you're in for a lot of sweating and praying. + +Meet your saviour! This system adds the ability to allow your system to upgrade +itself. Whenever you increment the version in your VERSION file, it can run a +custom script that will do everything you need AND keep others out until it is +done. Once the system is updated, the next thing to touch the code containing +the upgrade system will cause it to run. + +CAVEATS: while this system will work with MySQL, I **STRONGLY** recommend +against it. It was built using PostgreSQL, which has a rock solid transaction +system: if the upgrade fails, everything rolls-back and it is up to a developer +to figure out what went wrong--but the system is left in a CONSISTENT STATE. +With MySQL, this will only work with InnoDB tables--and only if ALL AFFECTED +TABLES ARE InnoDB. There are also many things that will cause an implicit +commit, meaning the code will think its in a transaction after that point, but +it actually isn't (which is possibly worse than not having transactional +capabilities at all). + +The first time this system is implemented, you need to be aware that it will +look for an "INITIALVERSION" value in your upgrade.xml file. This version +determines where it should start, so intermediary upgrade scripts will run. It +is important to realize, however, that this setting can cause grief in and of +itself: if you give the wrong version, scripts might run that shouldn't. This +is especially important for long-running projects that are expected to be able +to be installed at any version: subsequent releases should update this initial +version (or remove it) as necessary. + +MySQL TRANSACTION INFO::: http://dev.mysql.com/doc/refman/5.0/en/implicit-commit.html + +WORK FLOW: + + --> Is there an existing LOCK file? + YES:: + --> HALT (tell the user there's an upgrade in progress). + NO::: + --> System checks VERSION file vs. version in database + --> Does version file's version match database version? + YES::: + -- good to go. + -- CONTINUE + NO::: + --> CREATE LOCK FILE + --> find named script in upgrade.xml file + --> include script, create new class, call method (in upgrade.xml file) + --> did upgrade succeed? + YES::: + --> remove LOCK file + --> CONTINUE + NO::: + --> stop upgrade process. + --> HALT + --> (continues as before) \ No newline at end of file Modified: trunk/0.1/VERSION =================================================================== --- trunk/0.1/VERSION 2009-08-13 04:09:12 UTC (rev 38) +++ trunk/0.1/VERSION 2009-08-13 15:04:14 UTC (rev 39) @@ -1,6 +1,6 @@ ## Stores the current version of the cs-versionparse system, and it's source. ## Please do NOT modify this file. -VERSION: 0.2 +VERSION: 0.1 PROJECT: cs-webdbupgrade $HeadURL$ \ No newline at end of file Modified: trunk/0.1/cs_webdbupgrade.class.php =================================================================== --- trunk/0.1/cs_webdbupgrade.class.php 2009-08-13 04:09:12 UTC (rev 38) +++ trunk/0.1/cs_webdbupgrade.class.php 2009-08-13 15:04:14 UTC (rev 39) @@ -13,7 +13,6 @@ */ require_once(constant('LIBDIR') .'/cs-versionparse/cs_version.abstract.class.php'); -require_once(constant('LIBDIR') .'/cs_debug.php'); class cs_webdbupgrade extends cs_versionAbstract { @@ -47,16 +46,9 @@ /** Name (absolute location) of *.lock file that indicates an upgrade is running. */ private $lockfile; - /** Determines if an internal upgrade is happening (avoids some infinite loops) */ - private $internalUpgradeInProgress = false; - /** */ private $allowNoDBVersion=true; - /** Log messages to store during an internal upgrade (to avoid problems) */ - private $storedLogs = array(); - private $debugLogs=array(); - /** List of acceptable suffixes; example "1.0.0-BETA3" -- NOTE: these MUST be in * an order that reflects newest -> oldest; "ALPHA happens before BETA, etc. */ private $suffixList = array( @@ -66,17 +58,34 @@ ); //========================================================================= - public function __construct($versionFileLocation, $upgradeConfigFile, $lockFile='upgrade.lock') { + public function __construct($versionFileLocation, array $config) { - //setup configuration parameters for database connectivity. - $dbParams = array( - 'host' => constant(__CLASS__ .'-DB_CONNECT_HOST'), - 'port' => constant(__CLASS__ .'-DB_CONNECT_PORT'), - 'dbname' => constant(__CLASS__ .'-DB_CONNECT_DBNAME'), - 'user' => constant(__CLASS__ .'-DB_CONNECT_USER'), - 'password' => constant(__CLASS__ .'-DB_CONNECT_PASSWORD') - ); - $this->config['DBPARAMS'] = $dbParams; + //Handle the config array (cope with XML-ish array) + if(is_array($config)) { + //check if it is in the complex XML array style... + $keys = array_keys($config); + if(isset($config[$keys[0]]['type'])) { + $this->fix_xml_config($config); + $this->config = $this->tempXmlConfig; + } + else { + $this->config = $config; + } + } + else { + throw new exception(__METHOD__ .": no configuration available"); + } + + //cope with problems in CS-Content v1.0-ALPHA9 (or before)--see http://project.crazedsanity.com/extern/helpdesk/view?ID=281 + if(isset($this->config['DBPARMLINKER'])) { + $this->config['DBPARAMS'] = array(); + foreach($this->config['DBPARMLINKER'] as $i=>$loc) { + $this->config['DBPARAMS'][strtolower($i)] = $this->config[$loc]; + unset($this->config[$loc]); + } + unset($this->config['DBPARMLINKER']); + } + //Check for some required constants. $requisiteConstants = array('LIBDIR'); if(!defined('LIBDIR')) { @@ -94,46 +103,32 @@ require_once(constant('LIBDIR') .'/cs-phpxml/cs_phpxmlCreator.class.php'); require_once(constant('LIBDIR') .'/cs-phpxml/cs_arrayToPath.class.php'); + $this->versionFileLocation = $versionFileLocation; + $this->fsObj = new cs_fileSystem(constant('SITE_ROOT')); $this->gfObj = new cs_globalFunctions; if(defined('DEBUGPRINTOPT')) { $this->gfObj->debugPrintOpt = constant('DEBUGPRINTOPT'); } - if(!defined(__CLASS__ .'-DB_PRIMARYKEY') || !defined(__CLASS__ .'-DB_TABLE')) { + if(!isset($this->config['DB_PRIMARYKEY']) || !isset($this->config['DB_TABLE'])) { throw new exception(__METHOD__ .": no setting for DB_TABLE or DB_PRIMARYKEY, cannot continue"); } - else { - $this->config['DB_TABLE'] = constant(__CLASS__ .'-DB_TABLE'); - $this->config['DB_PRIMARYKEY'] = constant(__CLASS__ .'-DB_PRIMARYKEY'); - } $this->sequenceName = $this->config['DB_TABLE'] .'_'. $this->config['DB_PRIMARYKEY'] .'_seq'; if(!defined('DBTYPE')) { throw new exception(__METHOD__ .": required constant 'DBTYPE' not set"); } - - if(!file_exists($upgradeConfigFile) || !is_readable($upgradeConfigFile)) { - throw new exception(__METHOD__ .": required upgrade config file location (". $upgradeConfigFile .") not set or unreadable"); + if(!isset($this->config['CONFIG_FILE_LOCATION'])) { + throw new exception(__METHOD__ .": required setting 'CONFIG_FILE_LOCATION' not found"); } - else { - $this->config['UPGRADE_CONFIG_FILE'] = $upgradeConfigFile; - } if(!strlen($versionFileLocation) || !file_exists($versionFileLocation)) { throw new exception(__METHOD__ .": unable to locate version file (". $versionFileLocation .")"); } - $this->set_version_file_location($versionFileLocation); - - if(!defined(__CLASS__ .'-RWDIR') || !is_dir(constant(__CLASS__ .'-RWDIR')) || !is_readable(constant(__CLASS__ .'-RWDIR')) || !is_writable(constant(__CLASS__ .'-RWDIR'))) { - throw new exception(__METHOD__ .": missing RWDIR (". constant(__CLASS__ .'-RWDIR') .") or isn't readable/writable"); + if(!isset($this->config['RWDIR']) || !is_dir($this->config['RWDIR']) || !is_readable($this->config['RWDIR']) || !is_writable($this->config['RWDIR'])) { + throw new exception(__METHOD__ .": missing RWDIR (". $this->config['RWDIR'] .") or isn't readable/writable"); } - else { - $this->config['RWDIR'] = constant(__CLASS__ .'-RWDIR'); - } - if(is_null($lockFile) || !strlen($lockFile)) { - $lockFile = 'upgrade.lock'; - } - $this->lockfile = $this->config['RWDIR'] .'/'. $lockFile; + $this->lockfile = $this->config['RWDIR'] .'/upgrade.lock'; $this->db = new cs_phpDB(constant('DBTYPE')); try { @@ -145,15 +140,12 @@ if($this->check_lockfile()) { //there is an existing lockfile... - throw new exception(__METHOD__ .": upgrade in progress: ". $this->fsObj->read($this->lockfile)); + $this->error_handler(__METHOD__ .": upgrade in progress: ". $this->fsObj->read($this->lockfile)); } $this->check_internal_upgrades(); - - try { - $loggerDb = new cs_phpDB(constant('DBTYPE')); - $loggerDb->connect($this->config['DBPARAMS'], true); - $this->logsObj = new cs_webdblogger($loggerDb, "Upgrade ". $this->projectName, false); + try { + $this->connect_logger("Upgrade"); } catch(exception $e) { throw new exception(__METHOD__ .": failed to create logger::: ". $e->getMessage()); @@ -175,12 +167,17 @@ $this->config['UPGRADE_CONFIG_FILE'] = dirname(__FILE__) .'/upgrades/upgrade.xml'; - //set a status flag so we can store log messages (for now). - $this->internalUpgradeInProgress = true; + //connect the logger... + try { + $this->connect_logger("Internal Upgrade"); + } + catch(exception $e) { + $this->error_handler($e->getMessage()); + } //do stuff here... - $this->set_version_file_location(dirname(__FILE__) .'/VERSION'); + $this->versionFileLocation = dirname(__FILE__) .'/VERSION'; $this->read_version_file(); //if there is an error, then... uh... yeah. @@ -188,7 +185,7 @@ $this->get_database_version(); } catch(exception $e) { - throw new exception(__METHOD__ .": error while retrieving database version: ". $e->getMessage()); + #throw new exception(__METHOD__ .": error while retrieving database version: ". $e->getMessage()); //try creating the version. $this->load_initial_version(); @@ -196,13 +193,12 @@ //do upgrades here... $this->check_versions(true); - $this->internalUpgradeInProgress = false; //reset internal vars. - $this->set_version_file_location($oldVersionFileLocation); + $this->versionFileLocation = $oldVersionFileLocation; $this->config['UPGRADE_CONFIG_FILE'] = $oldUpgradeConfigFile; $this->read_version_file(); @@ -227,7 +223,7 @@ //check to see if the lock files for upgrading exist. if($this->upgrade_in_progress()) { - $this->do_log("Upgrade in progress", 'notice'); + $this->logsObj->log_by_class("Upgrade in progress", 'notice'); throw new exception(__METHOD__ .": upgrade in progress"); } else { @@ -329,7 +325,6 @@ //========================================================================= private function perform_upgrade() { - $this->logsObj->suspendLogging=true; //make sure there's not already a lockfile. if($this->upgrade_in_progress()) { //ew. Can't upgrade. @@ -339,7 +334,7 @@ $lockConfig = $this->upgrade_in_progress(TRUE); $this->fsObj->cd("/"); - $this->do_log("Starting upgrade process...", 'begin'); + $this->logsObj->log_by_class("Starting upgrade process...", 'begin'); //TODO: not only should the "create_file()" method be run, but also do a sanity check by calling lock_file_exists(). if($lockConfig === 0) { @@ -347,7 +342,7 @@ $this->error_handler(__METHOD__ .": failed to set 'upgrade in progress'"); } else { - $this->do_log(__METHOD__ .": result of creating lockfile: (". $lockConfig .")", 'debug'); + $this->logsObj->log_by_class(__METHOD__ .": result of creating lockfile: (". $lockConfig .")", 'debug'); //push data into our internal "config" array. $this->read_upgrade_config_file(); @@ -358,38 +353,39 @@ if($versionConflictInfo !== false) { - $this->do_log("Upgrading ". $versionConflictInfo ." versions, from " . + $this->logsObj->log_by_class("Upgrading ". $versionConflictInfo ." versions, from " . "(". $this->databaseVersion .") to (". $this->versionFileVersion .")", 'info'); } $upgradeList = $this->get_upgrade_list(); + try { $i=0; - $this->do_log(__METHOD__ .": starting to run through the upgrade list, starting at (". $this->databaseVersion ."), " . + $this->logsObj->log_by_class(__METHOD__ .": starting to run through the upgrade list, starting at (". $this->databaseVersion ."), " . "total number of upgrades to perform: ". count($upgradeList), 'debug'); $this->db->beginTrans(__METHOD__); foreach($upgradeList as $fromVersion=>$toVersion) { $details = __METHOD__ .": upgrading from ". $fromVersion ." to ". $toVersion ."... "; - $this->do_log($details, 'system'); + $this->logsObj->log_by_class($details, 'system'); $this->do_single_upgrade($fromVersion, $toVersion); $this->get_database_version(); $i++; $details = __METHOD__ .": finished upgrade #". $i .", now at version (". $this->databaseVersion .")"; - $this->do_log($details, 'system'); + $this->logsObj->log_by_class($details, 'system'); } if($i < count($upgradeList)) { - $this->do_log(__METHOD__ .": completed upgrade ". $i ." of ". count($upgradeList), 'debug'); + $this->logsObj->log_by_class(__METHOD__ .": completed upgrade ". $i ." of ". count($upgradeList), 'debug'); } else { if($this->databaseVersion == $this->versionFileVersion) { - $this->do_log(__METHOD__ .": finished upgrading after performing (". $i .") upgrades", 'debug'); + $this->logsObj->log_by_class(__METHOD__ .": finished upgrading after performing (". $i .") upgrades", 'debug'); $this->newVersion = $this->databaseVersion; } else { - $this->do_log(__METHOD__ .": upgradeList::: ". $this->gfObj->debug_print($upgradeList,0), 'debug'); + $this->logsObj->log_by_class(__METHOD__ .": upgradeList::: ". $this->gfObj->debug_print($upgradeList,0), 'debug'); $this->error_handler(__METHOD__ .": finished upgrade, but version wasn't updated (expecting '". $this->versionFileVersion ."', got '". $this->databaseVersion ."')!!!"); } } @@ -398,16 +394,12 @@ $this->db->commitTrans(); } catch(exception $e) { - $transactionStatus = $this->db->get_transaction_status(false); - $this->error_handler(__METHOD__ .": transaction status=(". $transactionStatus ."), upgrade aborted:::". $e->getMessage()); + $this->error_handler(__METHOD__ .": upgrade aborted:::". $e->getMessage()); $this->db->rollbackTrans(); } - $this->logsObj->suspendLogging=false; - $this->do_log("Upgrade process complete", 'end'); + $this->logsObj->log_by_class("Upgrade process complete", 'end'); } } - $this->logsObj->suspendLogging=false; - $logsHandled = $this->logsObj->handle_suspended_logs(); }//end perform_upgrade() //========================================================================= @@ -615,7 +607,7 @@ $this->error_handler(__METHOD__ .": target version not specified, unable to proceed with upgrade for ". $versionIndex); } } - $this->do_log("Finished upgrade to ". $this->newVersion, 'system'); + $this->logsObj->log_by_class("Finished upgrade to ". $this->newVersion, 'system'); }//end do_single_upgrade() //========================================================================= @@ -627,14 +619,19 @@ * so the version there is consistent with all the others. */ protected function update_database_version($newVersionString) { - $versionInfo = $this->parse_version_string($newVersionString); + $versionArr = $this->parse_version_string($newVersionString); - $sql = "UPDATE ". $this->config['DB_TABLE'] ." SET version_string='". - $this->gfObj->cleanString($versionInfo['version_string'], 'sql') - ."' WHERE project_name='". - $this->gfObj->cleanString($this->projectName, 'sql') ."'"; + $queryArr = array(); + foreach($versionArr as $index=>$value) { + $queryArr[$index] = "SELECT internal_data_set_value('". $index ."', '". $value ."');"; + } + $updateData = $versionArr; + $sql = "UPDATE ". $this->config['DB_TABLE'] ." SET ". + $this->gfObj->string_from_array($updateData, 'update', null, 'sql') ." WHERE " . + "project_name='". $this->gfObj->cleanString($this->projectName, 'sql') ."'"; + $updateRes = $this->db->run_update($sql,false); if($updateRes == 1) { $retval = $updateRes; @@ -674,7 +671,7 @@ } if(!$retval) { - $this->do_log("Version check failed, versionString=(". $versionString ."), checkVersion=(". $this->newVersion .")", 'FATAL'); + $this->logsObj->log_by_class("Version check failed, versionString=(". $versionString ."), checkVersion=(". $this->newVersion .")", 'FATAL'); } } @@ -692,16 +689,20 @@ private function do_scripted_upgrade(array $upgradeData) { $myConfigFile = $upgradeData['SCRIPT_NAME']; - $this->do_log("Preparing to run script '". $myConfigFile ."'", 'debug'); + $this->logsObj->log_by_class("Preparing to run script '". $myConfigFile ."'", 'debug'); //we've got the filename, see if it exists. - - $scriptsDir = dirname($this->config['UPGRADE_CONFIG_FILE']); + if(isset($this->config['UPGRADE_SCRIPTS_DIR'])) { + $scriptsDir = $this->config['UPGRADE_SCRIPTS_DIR']; + } + else { + $this->logsObj->log_by_class("No UPGRADE_SCRIPTS_DIR config setting", 'warning'); + $scriptsDir = dirname($this->config['UPGRADE_CONFIG_FILE']); + } $fileName = $scriptsDir .'/'. $myConfigFile; - if(file_exists($fileName)) { - - $this->do_log("(". __CLASS__ .") Performing scripted upgrade (". $myConfigFile .") from file '". $fileName ."'", 'DEBUG'); + + $this->logsObj->log_by_class("Performing scripted upgrade (". $myConfigFile .")", 'DEBUG'); $createClassName = $upgradeData['CLASS_NAME']; $classUpgradeMethod = $upgradeData['CALL_METHOD']; require_once($fileName); @@ -714,12 +715,12 @@ if($upgradeResult === true) { //yay, it worked! - $this->do_log("Upgrade succeeded (". $upgradeResult .")", 'success'); + $this->logsObj->log_by_class("Upgrade succeeded (". $upgradeResult .")", 'success'); } else { $this->error_handler(__METHOD__ .": upgrade failed (". $upgradeResult .")"); } - $this->do_log("Finished running ". $createClassName ."::". $classUpgradeMethod ."(), result was (". $upgradeResult .")", 'debug'); + $this->logsObj->log_by_class("Finished running ". $createClassName ."::". $classUpgradeMethod ."(), result was (". $upgradeResult .")", 'debug'); } else { $this->error_handler(__METHOD__ .": upgrade method doesn't exist (". $createClassName ."::". $classUpgradeMethod @@ -792,11 +793,11 @@ $retval[$matchVersion] = $data['TARGET_VERSION']; } else { - $this->do_log(__METHOD__ .": entry in upgrade.xml (". $matchVersion .") is higher than the VERSION file (". $this->versionFileVersion .")", 'warning'); + $this->logsObj->log_by_class(__METHOD__ .": entry in upgrade.xml (". $matchVersion .") is higher than the VERSION file (". $this->versionFileVersion .")", 'warning'); } } else { - $this->do_log(__METHOD__ .": SKIPPING (". $matchVersion .")", 'debug'); + $this->logsObj->log_by_class(__METHOD__ .": SKIPPING (". $matchVersion .")", 'debug'); } } @@ -806,7 +807,7 @@ } else { //no intermediary upgrades: just pass back the latest version. - $this->do_log(__METHOD__ .": no intermediary upgrades", 'debug'); + $this->logsObj->log_by_class(__METHOD__ .": no intermediary upgrades", 'debug'); $retval[$dbVersion] = $this->versionFileVersion; } @@ -860,7 +861,7 @@ $a2p = new cs_arrayToPath($config); } catch(exception $e) { - $this->do_log(__METHOD__ .': encountered exception: '. $e->getMessage()); + $this->logsObj->log_by_class(__METHOD__ .': encountered exception: '. $e->getMessage()); $this->error_handler($e->getMessage()); } if(!is_array($this->tempXmlConfig)) { @@ -870,7 +871,7 @@ $myA2p = new cs_arrayToPath(&$this->tempXmlConfig); } catch(exception $e) { - $this->do_log(__METHOD__ .': encountered exception: '. $e->getMessage()); + $this->logsObj->log_by_class(__METHOD__ .': encountered exception: '. $e->getMessage()); $this->error_handler($e->getMessage()); } @@ -934,7 +935,7 @@ $logRes = 'Failed to load'; $logType = 'error'; } - $this->do_log($logRes .' table ('. $this->config['DB_TABLE'] .') into ' . + $this->logsObj->log_by_class($logRes .' table ('. $this->config['DB_TABLE'] .') into ' . 'database::: '. $loadTableResult, $logType); return($loadTableResult); @@ -1030,12 +1031,7 @@ //========================================================================= public function error_handler($details) { //log the error. - if(!is_object($this->logsObj)) { - throw new exception(__METHOD__ .": error while running an internal upgrade::: ". $details); - } - if($this->internalUpgradeInProgress === false) { - $this->do_log($details, 'exception in code'); - } + $this->logsObj->log_by_class($details, 'exception in code'); //now throw an exception so other code can catch it. throw new exception($details); @@ -1048,24 +1044,19 @@ public function load_initial_version() { //if there's an INITIAL_VERSION in the upgrade config file, use that. $this->read_upgrade_config_file(); - $insertData = array(); if(isset($this->config['UPGRADELIST']['INITIALVERSION'])) { - $parseThis = $this->config['UPGRADELIST']['INITIALVERSION']; + $insertData = $this->parse_version_string($this->config['UPGRADELIST']['INITIALVERSION']); } else { - $parseThis = $this->versionFileVersion; + $insertData = $this->parse_version_string($this->versionFileVersion); } - $versionInfo = $this->parse_version_string($parseThis); - $insertData = array( - 'project_name' => $this->projectName, - 'version_string' => $versionInfo['version_string'] - ); + $insertData['project_name'] = $this->projectName; $sql = 'INSERT INTO '. $this->config['DB_TABLE'] . $this->gfObj->string_from_array($insertData, 'insert'); if($this->db->run_insert($sql, $this->sequenceName)) { $loadRes = true; - $this->do_log("Created data for '". $this->projectName ."' with version '". $insertData['version_string'] ."'", 'initialize'); + $this->logsObj->log_by_class("Created data for '". $this->projectName ."' with version '". $insertData['version_string'] ."'", 'initialize'); } else { $this->error_handler(__METHOD__ .": failed to load initial version::: ". $e->getMessage()); @@ -1078,15 +1069,11 @@ //========================================================================= - protected function do_log($message, $type) { - $this->debugLogs[] = array('project'=>$this->projectName,'upgradeFile'=>$this->config['UPGRADE_CONFIG_FILE'],'message'=>$message,'type'=>$type); - if($this->internalUpgradeInProgress === true) { - $this->storedLogs[] = func_get_args(); - } - else { - $this->logsObj->log_by_class($message, $type); - } - }//end do_log() + private function connect_logger($logCategory) { + $loggerDb = new cs_phpDB(constant('DBTYPE')); + $loggerDb->connect($this->config['DBPARAMS'], true); + $this->logsObj = new cs_webdblogger($loggerDb, $logCategory); + }//end connect_logger() //========================================================================= Deleted: trunk/0.1/exampleUpgrades/upgrade.xml =================================================================== --- trunk/0.1/exampleUpgrades/upgrade.xml 2009-08-06 14:53:12 UTC (rev 28) +++ trunk/0.1/exampleUpgrades/upgrade.xml 2009-08-13 15:04:14 UTC (rev 39) @@ -1,35 +0,0 @@ -<upgrade> - <system_note>To determine which section in matching to use, heed only the information - beneath the tag that indicates the current database version (for 5.2.4, - you would find information under matching for "v5.2.4"). This section - indicates the version that it should upgrade the database to - ("target_version"), the name of the script ("script_name"), the class name - ("class_name"), and the name of the method within that class ("call_method") - to call in order to perform the upgrade. The method should return TRUE on - success: anything else would indicate failure. Upgrade failure may leave - the system in an inconsistent state. - - IMPORTANT: in order to facilitate doing multiple version upgrades, the name - of the class must be UNIQUE to all the other classes. For this reason, the - class name should be something like "v1_0_0_ALPHA1__to__v1_0_0_ALPHA2". - - REMEMBER: the "target_version" should NEVER be higher than the next item - beneath matching; this will cause horrible logic errors, causing an upgsrade - to get skipped, or an exception to be thrown, potentially leaving the system - in an unstable state. Unstable is bad, m'kay?</system_note> - - <matching> - <v1.2.0-ALPHA3> - <target_version>1.2.0-ALPHA4</target_version> - <script_name>upgradeTo1.2.0-ALPHA4.php</script_name> - <class_name>upgrade_to_1_2_0_ALPHA4</class_name> - <call_method>run_upgrade</call_method> - </v1.2.0-ALPHA3> - <v1.2.0-ALPHA6> - <target_version>1.2.0-ALPHA7</target_version> - <script_name>upgradeTo1.2.0-ALPHA7.php</script_name> - <class_name>upgrade_to_1_2_0_ALPHA7</class_name> - <call_method>run_upgrade</call_method> - </v1.2.0-ALPHA6> - </matching> -</upgrade> Copied: trunk/0.1/exampleUpgrades/upgrade.xml (from rev 28, trunk/0.1/exampleUpgrades/upgrade.xml) =================================================================== --- trunk/0.1/exampleUpgrades/upgrade.xml (rev 0) +++ trunk/0.1/exampleUpgrades/upgrade.xml 2009-08-13 15:04:14 UTC (rev 39) @@ -0,0 +1,35 @@ +<upgrade> + <system_note>To determine which section in matching to use, heed only the information + beneath the tag that indicates the current database version (for 5.2.4, + you would find information under matching for "v5.2.4"). This section + indicates the version that it should upgrade the database to + ("target_version"), the name of the script ("script_name"), the class name + ("class_name"), and the name of the method within that class ("call_method") + to call in order to perform the upgrade. The method should return TRUE on + success: anything else would indicate failure. Upgrade failure may leave + the system in an inconsistent state. + + IMPORTANT: in order to facilitate doing multiple version upgrades, the name + of the class must be UNIQUE to all the other classes. For this reason, the + class name should be something like "v1_0_0_ALPHA1__to__v1_0_0_ALPHA2". + + REMEMBER: the "target_version" should NEVER be higher than the next item + beneath matching; this will cause horrible logic errors, causing an upgsrade + to get skipped, or an exception to be thrown, potentially leaving the system + in an unstable state. Unstable is bad, m'kay?</system_note> + + <matching> + <v1.2.0-ALPHA3> + <target_version>1.2.0-ALPHA4</target_version> + <script_name>upgradeTo1.2.0-ALPHA4.php</script_name> + <class_name>upgrade_to_1_2_0_ALPHA4</class_name> + <call_method>run_upgrade</call_method> + </v1.2.0-ALPHA3> + <v1.2.0-ALPHA6> + <target_version>1.2.0-ALPHA7</target_version> + <script_name>upgradeTo1.2.0-ALPHA7.php</script_name> + <class_name>upgrade_to_1_2_0_ALPHA7</class_name> + <call_method>run_upgrade</call_method> + </v1.2.0-ALPHA6> + </matching> +</upgrade> Deleted: trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA4.php =================================================================== --- trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA4.php 2009-08-06 14:53:12 UTC (rev 28) +++ trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA4.php 2009-08-13 15:04:14 UTC (rev 39) @@ -1,153 +0,0 @@ -<?php - -class upgrade_to_1_2_0_ALPHA4 extends dbAbstract { - - private $logsObj; - - //========================================================================= - public function __construct(cs_phpDB &$db) { - if(!$db->is_connected()) { - throw new exception(__METHOD__ .": database is not connected"); - } - $this->db = $db; - - $this->logsObj = new logsClass($this->db, 'Upgrade'); - - $this->gfObj = new cs_globalFunctions; - $this->gfObj->debugPrintOpt = 1; - }//end __construct() - //========================================================================= - - - - //========================================================================= - public function run_upgrade() { - - $this->db->beginTrans(__METHOD__); - - - $this->run_schema_changes(); - $this->update_tag_icons(); - $this->update_config_file(); - - - $this->db->commitTrans(__METHOD__); - - return('Upgrade complete'); - }//end run_upgrade() - //========================================================================= - - - - //========================================================================= - private function run_schema_changes() { - - $this->gfObj->debug_print(__METHOD__ .": running SQL file..."); - $this->run_sql_file(dirname(__FILE__) .'/../docs/sql/upgrades/upgradeTo1.2.0-ALPHA2.sql'); - - $details = "Executed SQL file, '". $this->lastSQLFile ."'. Encoded contents::: ". - base64_encode($this->fsObj->read($this->lastSQLFile)); - $this->logsObj->log_by_class($details, 'system'); - - - - $this->gfObj->debug_print(__METHOD__ .": running SQL file..."); - $this->run_sql_file(dirname(__FILE__) .'/../docs/sql/upgrades/upgradeTo1.2.0-ALPHA4.sql'); - - $details = "Executed SQL file, '". $this->lastSQLFile ."'. Encoded contents::: ". - base64_encode($this->fsObj->read($this->lastSQLFile)); - $this->logsObj->log_by_class($details, 'system'); - - }//end run_schema_changes() - //========================================================================= - - - - //========================================================================= - private function update_tag_icons() { - - $sql = "SELECT tag_name_id, name, icon_name FROM tag_name_table ORDER BY tag_name_id"; - if($this->run_sql($sql) && $this->lastNumrows > 1) { - $allTags = $this->db->farray_fieldnames('name', 'tag_name_id'); - - $iconMods = array( - 'critical' => 'red_x', - 'bug' => 'bug', - 'feature request' => 'feature_request', - 'committed' => 'check_red', - 'verified' => 'check_yellow', - 'released' => 'check_green' - ); - - $updates = 0; - foreach($iconMods as $name=>$icon) { - if(isset($allTags[$name])) { - //update. - $sql = "UPDATE tag_name_table SET icon_name='". $icon ."' WHERE tag_name_id=". $allTags[$name]['tag_name_id']; - } - else { - //insert. - $sql = "INSERT INTO tag_name_table (name, icon_name) VALUES ('". $name ."', '". $icon ."');"; - } - $this->run_sql($sql); - $updates += $this->lastNumrows; - } - } - else { - throw new exception(__METHOD__ .": failed to retrieve tag names"); - } - - }//end update_tag_modifiers() - //========================================================================= - - - - //========================================================================= - public function update_config_file() { - $fs = new cs_fileSystemClass(dirname(__FILE__) .'/../'); - $sampleXmlObj = new XMLParser($fs->read('docs/samples/sample_config.xml')); - $siteXmlObj = new XMLParser($fs->read(CONFIG_FILE_LOCATION)); - - $updateXml = new xmlCreator(); - $updateXml->load_xmlparser_data($siteXmlObj); - - - //BACKUP ORIGINAL XML CONFIG... - $backupFile = 'lib/__BACKUP__'. time() .'__'. CONFIG_FILENAME; - $fs->create_file($backupFile); - $fs->openFile($backupFile); - $fs->write($updateXml->create_xml_string()); - - $sampleIndexes = $sampleXmlObj->get_tree(TRUE); - $sampleIndexes = $sampleIndexes['CONFIG']; - - $siteConfigIndexes = $siteXmlObj->get_tree(TRUE); - $siteConfigIndexes = $siteConfigIndexes['CONFIG']; - - foreach($sampleIndexes as $indexName=>$indexValue) { - $path = '/CONFIG/'. $indexName; - $attributes = $sampleXmlObj->get_attribute($path); - #debug_print(__METHOD__ .": attributes from sample (/CONFIG/". $indexName ."::: ",1); - #debug_print($attributes,1); - debug_print(__METHOD__ .': indexName=('. $indexName .'), indexValue=('. $indexValue .'), original config value=('. $siteConfigIndexes[$indexName] .')'); - - //add tag if it's not there, update values otherwise. - $tagValue = $attributes['DEFAULT']; - if(isset($siteConfigIndexes[$indexName])) { - $tagValue = $siteConfigIndexes[$indexName]; - } - elseif($indexName == 'PHPMAILER_HOST' && isset($siteConfigIndexes['CONFIG_EMAIL_SERVER_IP'])) { - $tagValue = $siteConfigIndexes['CONFIG_EMAIL_SERVER_IP']; - $updateXml->remove_path('/CONFIG/CONFIG_EMAIL_SERVER_IP'); - } - $updateXml->add_tag($path, $tagValue, $attributes); - } - - $this->gfObj->debug_print($this->gfObj->cleanString($updateXml->create_xml_string(), 'htmlentity_plus_brackets')); - $fs->openFile(CONFIG_FILE_LOCATION); - $fs->write($updateXml->create_xml_string()); - }//end update_config_file() - //========================================================================= -} - -?> Copied: trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA4.php (from rev 28, trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA4.php) =================================================================== --- trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA4.php (rev 0) +++ trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA4.php 2009-08-13 15:04:14 UTC (rev 39) @@ -0,0 +1,153 @@ +<?php + +class upgrade_to_1_2_0_ALPHA4 extends dbAbstract { + + private $logsObj; + + //========================================================================= + public function __construct(cs_phpDB &$db) { + if(!$db->is_connected()) { + throw new exception(__METHOD__ .": database is not connected"); + } + $this->db = $db; + + $this->logsObj = new logsClass($this->db, 'Upgrade'); + + $this->gfObj = new cs_globalFunctions; + $this->gfObj->debugPrintOpt = 1; + }//end __construct() + //========================================================================= + + + + //========================================================================= + public function run_upgrade() { + + $this->db->beginTrans(__METHOD__); + + + $this->run_schema_changes(); + $this->update_tag_icons(); + $this->update_config_file(); + + + $this->db->commitTrans(__METHOD__); + + return('Upgrade complete'); + }//end run_upgrade() + //========================================================================= + + + + //========================================================================= + private function run_schema_changes() { + + $this->gfObj->debug_print(__METHOD__ .": running SQL file..."); + $this->run_sql_file(dirname(__FILE__) .'/../docs/sql/upgrades/upgradeTo1.2.0-ALPHA2.sql'); + + $details = "Executed SQL file, '". $this->lastSQLFile ."'. Encoded contents::: ". + base64_encode($this->fsObj->read($this->lastSQLFile)); + $this->logsObj->log_by_class($details, 'system'); + + + + $this->gfObj->debug_print(__METHOD__ .": running SQL file..."); + $this->run_sql_file(dirname(__FILE__) .'/../docs/sql/upgrades/upgradeTo1.2.0-ALPHA4.sql'); + + $details = "Executed SQL file, '". $this->lastSQLFile ."'. Encoded contents::: ". + base64_encode($this->fsObj->read($this->lastSQLFile)); + $this->logsObj->log_by_class($details, 'system'); + + }//end run_schema_changes() + //========================================================================= + + + + //========================================================================= + private function update_tag_icons() { + + $sql = "SELECT tag_name_id, name, icon_name FROM tag_name_table ORDER BY tag_name_id"; + if($this->run_sql($sql) && $this->lastNumrows > 1) { + $allTags = $this->db->farray_fieldnames('name', 'tag_name_id'); + + $iconMods = array( + 'critical' => 'red_x', + 'bug' => 'bug', + 'feature request' => 'feature_request', + 'committed' => 'check_red', + 'verified' => 'check_yellow', + 'released' => 'check_green' + ); + + $updates = 0; + foreach($iconMods as $name=>$icon) { + if(isset($allTags[$name])) { + //update. + $sql = "UPDATE tag_name_table SET icon_name='". $icon ."' WHERE tag_name_id=". $allTags[$name]['tag_name_id']; + } + else { + //insert. + $sql = "INSERT INTO tag_name_table (name, icon_name) VALUES ('". $name ."', '". $icon ."');"; + } + $this->run_sql($sql); + $updates += $this->lastNumrows; + } + } + else { + throw new exception(__METHOD__ .": failed to retrieve tag names"); + } + + }//end update_tag_modifiers() + //========================================================================= + + + + //========================================================================= + public function update_config_file() { + $fs = new cs_fileSystemClass(dirname(__FILE__) .'/../'); + $sampleXmlObj = new XMLParser($fs->read('docs/samples/sample_config.xml')); + $siteXmlObj = new XMLParser($fs->read(CONFIG_FILE_LOCATION)); + + $updateXml = new xmlCreator(); + $updateXml->load_xmlparser_data($siteXmlObj); + + + //BACKUP ORIGINAL XML CONFIG... + $backupFile = 'lib/__BACKUP__'. time() .'__'. CONFIG_FILENAME; + $fs->create_file($backupFile); + $fs->openFile($backupFile); + $fs->write($updateXml->create_xml_string()); + + $sampleIndexes = $sampleXmlObj->get_tree(TRUE); + $sampleIndexes = $sampleIndexes['CONFIG']; + + $siteConfigIndexes = $siteXmlObj->get_tree(TRUE); + $siteConfigIndexes = $siteConfigIndexes['CONFIG']; + + foreach($sampleIndexes as $indexName=>$indexValue) { + $path = '/CONFIG/'. $indexName; + $attributes = $sampleXmlObj->get_attribute($path); + #debug_print(__METHOD__ .": attributes from sample (/CONFIG/". $indexName ."::: ",1); + #debug_print($attributes,1); + debug_print(__METHOD__ .': indexName=('. $indexName .'), indexValue=('. $indexValue .'), original config value=('. $siteConfigIndexes[$indexName] .')'); + + //add tag if it's not there, update values otherwise. + $tagValue = $attributes['DEFAULT']; + if(isset($siteConfigIndexes[$indexName])) { + $tagValue = $siteConfigIndexes[$indexName]; + } + elseif($indexName == 'PHPMAILER_HOST' && isset($siteConfigIndexes['CONFIG_EMAIL_SERVER_IP'])) { + $tagValue = $siteConfigIndexes['CONFIG_EMAIL_SERVER_IP']; + $updateXml->remove_path('/CONFIG/CONFIG_EMAIL_SERVER_IP'); + } + $updateXml->add_tag($path, $tagValue, $attributes); + } + + $this->gfObj->debug_print($this->gfObj->cleanString($updateXml->create_xml_string(), 'htmlentity_plus_brackets')); + $fs->openFile(CONFIG_FILE_LOCATION); + $fs->write($updateXml->create_xml_string()); + }//end update_config_file() + //========================================================================= +} + +?> Deleted: trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA7.php =================================================================== --- trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA7.php 2009-08-06 14:53:12 UTC (rev 28) +++ trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA7.php 2009-08-13 15:04:14 UTC (rev 39) @@ -1,54 +0,0 @@ -<?php - -class upgrade_to_1_2_0_ALPHA7 extends dbAbstract { - - private $logsObj; - - //========================================================================= - public function __construct(cs_phpDB &$db) { - if(!$db->is_connected()) { - throw new exception(__METHOD__ .": database is not connected"); - } - $this->db = $db; - - $this->logsObj = new logsClass($this->db, 'Upgrade'); - - $this->gfObj = new cs_globalFunctions; - $this->gfObj->debugPrintOpt = 1; - }//end __construct() - //========================================================================= - - - - //========================================================================= - public function run_upgrade() { - - $this->db->beginTrans(__METHOD__); - - - $this->run_schema_changes(); - - - $this->db->commitTrans(__METHOD__); - - return('Upgrade complete'); - }//end run_upgrade() - //========================================================================= - - - - //========================================================================= - private function run_schema_changes() { - - $this->gfObj->debug_print(__METHOD__ .": running SQL file..."); - $this->run_sql_file(dirname(__FILE__) .'/../docs/sql/upgrades/upgradeTo1.2.0-ALPHA7.sql'); - - $details = "Executed SQL file, '". $this->lastSQLFile ."'. Encoded contents::: ". - base64_encode($this->fsObj->read($this->lastSQLFile)); - $this->logsObj->log_by_class($details, 'system'); - - }//end run_schema_changes() - //========================================================================= -} - -?> Copied: trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA7.php (from rev 28, trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA7.php) =================================================================== --- trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA7.php (rev 0) +++ trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA7.php 2009-08-13 15:04:14 UTC (rev 39) @@ -0,0 +1,54 @@ +<?php + +class upgrade_to_1_2_0_ALPHA7 extends dbAbstract { + + private $logsObj; + + //========================================================================= + public function __construct(cs_phpDB &$db) { + if(!$db->is_connected()) { + throw new exception(__METHOD__ .": database is not connected"); + } + $this->db = $db; + + $this->logsObj = new logsClass($this->db, 'Upgrade'); + + $this->gfObj = new cs_globalFunctions; + $this->gfObj->debugPrintOpt = 1; + }//end __construct() + //========================================================================= + + + + //========================================================================= + public function run_upgrade() { + + $this->db->beginTrans(__METHOD__); + + + $this->run_schema_changes(); + + + $this->db->commitTrans(__METHOD__); + + return('Upgrade complete'); + }//end run_upgrade() + //========================================================================= + + + + //========================================================================= + private function run_schema_changes() { + + $this->gfObj->debug_print(__METHOD__ .": running SQL file..."); + $this->run_sql_file(dirname(__FILE__) .'/../docs/sql/upgrades/upgradeTo1.2.0-ALPHA7.sql'); + + $details = "Executed SQL file, '". $this->lastSQLFile ."'. Encoded contents::: ". + base64_encode($this-... [truncated message content] |
From: <cra...@us...> - 2009-08-13 04:09:27
|
Revision: 38 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=38&view=rev Author: crazedsanity Date: 2009-08-13 04:09:12 +0000 (Thu, 13 Aug 2009) Log Message: ----------- Remove some debugging. NOTE::: this version seems pretty stable, but it is dependent on unreleased cs-webdblogger v0.2.0. Using older 0.1.x code will cause errors, as this calls methods in that library that wouldn't exist yet. /cs_webdbupgrade.class.php: * perform_upgrade(): -- remove debug printing * do_log(): -- remove debug logging. Modified Paths: -------------- trunk/0.1/cs_webdbupgrade.class.php Modified: trunk/0.1/cs_webdbupgrade.class.php =================================================================== --- trunk/0.1/cs_webdbupgrade.class.php 2009-08-13 03:19:31 UTC (rev 37) +++ trunk/0.1/cs_webdbupgrade.class.php 2009-08-13 04:09:12 UTC (rev 38) @@ -408,7 +408,6 @@ } $this->logsObj->suspendLogging=false; $logsHandled = $this->logsObj->handle_suspended_logs(); - $this->gfObj->debug_print(__METHOD__ .": done, handled (". $logsHandled .") logs that had been suspended... ",1); }//end perform_upgrade() //========================================================================= @@ -1080,7 +1079,6 @@ //========================================================================= protected function do_log($message, $type) { - $this->gfObj->debug_print(__METHOD__ .": loggerSuspend=(". $this->logsObj->suspendLogging ."), type=(". $type ."), MESSAGE::: ". $message,1); $this->debugLogs[] = array('project'=>$this->projectName,'upgradeFile'=>$this->config['UPGRADE_CONFIG_FILE'],'message'=>$message,'type'=>$type); if($this->internalUpgradeInProgress === true) { $this->storedLogs[] = func_get_args(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-08-13 03:19:40
|
Revision: 37 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=37&view=rev Author: crazedsanity Date: 2009-08-13 03:19:31 +0000 (Thu, 13 Aug 2009) Log Message: ----------- INTERMEDIATE: fixes for logging + some debugging. /cs_webdbupgrade.class.php: * __construct(): -- better checking on the value of $lockFile -- drop some debugging -- connect logger manually instead of calling connect_logger() * check_internal_upgrades(): -- remove lots of debugging * perform_upgrade(): -- suspend logging for the entire method & handle the pending logs at the very end. -- added some debugging -- NOTE::: logging should only be suspended if $this->projectName matches "cs-webdblogger". * error_handler(): -- emit debugging messages * do_log(): -- emit debugging messages * connect_logger() [DELETED]: -- stop allowing methods to call this... allowing this can lead to situations where it overruns the database server with connections. Modified Paths: -------------- trunk/0.1/cs_webdbupgrade.class.php Modified: trunk/0.1/cs_webdbupgrade.class.php =================================================================== --- trunk/0.1/cs_webdbupgrade.class.php 2009-08-11 18:51:07 UTC (rev 36) +++ trunk/0.1/cs_webdbupgrade.class.php 2009-08-13 03:19:31 UTC (rev 37) @@ -130,7 +130,7 @@ else { $this->config['RWDIR'] = constant(__CLASS__ .'-RWDIR'); } - if(!is_string($lockFile)) { + if(is_null($lockFile) || !strlen($lockFile)) { $lockFile = 'upgrade.lock'; } $this->lockfile = $this->config['RWDIR'] .'/'. $lockFile; @@ -148,19 +148,17 @@ throw new exception(__METHOD__ .": upgrade in progress: ". $this->fsObj->read($this->lockfile)); } -$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); - $this->check_internal_upgrades(); -$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); - try { - $this->connect_logger(); + try { + $loggerDb = new cs_phpDB(constant('DBTYPE')); + $loggerDb->connect($this->config['DBPARAMS'], true); + $this->logsObj = new cs_webdblogger($loggerDb, "Upgrade ". $this->projectName, false); } catch(exception $e) { throw new exception(__METHOD__ .": failed to create logger::: ". $e->getMessage()); } - $this->gfObj->debug_print($this,1); $this->check_versions(false); }//end __construct() //========================================================================= @@ -172,22 +170,18 @@ * Determine if there are any upgrades that need to be performed... */ private function check_internal_upgrades() { -$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); $oldVersionFileLocation = $this->versionFileLocation; $oldUpgradeConfigFile = $this->config['UPGRADE_CONFIG_FILE']; $this->config['UPGRADE_CONFIG_FILE'] = dirname(__FILE__) .'/upgrades/upgrade.xml'; -$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); //set a status flag so we can store log messages (for now). $this->internalUpgradeInProgress = true; -$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); //do stuff here... $this->set_version_file_location(dirname(__FILE__) .'/VERSION'); $this->read_version_file(); -$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); //if there is an error, then... uh... yeah. try { @@ -201,22 +195,16 @@ } //do upgrades here... -$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); $this->check_versions(true); -$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); $this->internalUpgradeInProgress = false; -$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); //reset internal vars. $this->set_version_file_location($oldVersionFileLocation); -$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); $this->config['UPGRADE_CONFIG_FILE'] = $oldUpgradeConfigFile; -$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); $this->read_version_file(); -$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); }//end check_internal_upgrades() //========================================================================= @@ -341,6 +329,7 @@ //========================================================================= private function perform_upgrade() { + $this->logsObj->suspendLogging=true; //make sure there's not already a lockfile. if($this->upgrade_in_progress()) { //ew. Can't upgrade. @@ -409,12 +398,17 @@ $this->db->commitTrans(); } catch(exception $e) { - $this->error_handler(__METHOD__ .": upgrade aborted:::". $e->getMessage()); + $transactionStatus = $this->db->get_transaction_status(false); + $this->error_handler(__METHOD__ .": transaction status=(". $transactionStatus ."), upgrade aborted:::". $e->getMessage()); $this->db->rollbackTrans(); } + $this->logsObj->suspendLogging=false; $this->do_log("Upgrade process complete", 'end'); } } + $this->logsObj->suspendLogging=false; + $logsHandled = $this->logsObj->handle_suspended_logs(); + $this->gfObj->debug_print(__METHOD__ .": done, handled (". $logsHandled .") logs that had been suspended... ",1); }//end perform_upgrade() //========================================================================= @@ -1037,14 +1031,8 @@ //========================================================================= public function error_handler($details) { //log the error. - $this->gfObj->debug_print($this->debugLogs,1); if(!is_object($this->logsObj)) { - if($this->internalUpgradeInProgress === true) { - throw new exception(__METHOD__ .": error while running an internal upgrade::: ". $details); - } - else { - $this->connect_logger(); - } + throw new exception(__METHOD__ .": error while running an internal upgrade::: ". $details); } if($this->internalUpgradeInProgress === false) { $this->do_log($details, 'exception in code'); @@ -1091,24 +1079,8 @@ //========================================================================= - private function connect_logger($logCategory=null) { - - cs_debug_backtrace(1); - - if(is_null($logCategory) || !strlen($logCategory)) { - $logCategory = "Upgrade ". $this->projectName; - } - - $loggerDb = new cs_phpDB(constant('DBTYPE')); - $loggerDb->connect($this->config['DBPARAMS'], true); - $this->logsObj = new cs_webdblogger($loggerDb, $logCategory, false); - }//end connect_logger() - //========================================================================= - - - - //========================================================================= protected function do_log($message, $type) { + $this->gfObj->debug_print(__METHOD__ .": loggerSuspend=(". $this->logsObj->suspendLogging ."), type=(". $type ."), MESSAGE::: ". $message,1); $this->debugLogs[] = array('project'=>$this->projectName,'upgradeFile'=>$this->config['UPGRADE_CONFIG_FILE'],'message'=>$message,'type'=>$type); if($this->internalUpgradeInProgress === true) { $this->storedLogs[] = func_get_args(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-08-11 18:51:15
|
Revision: 36 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=36&view=rev Author: crazedsanity Date: 2009-08-11 18:51:07 +0000 (Tue, 11 Aug 2009) Log Message: ----------- INTERMEDIATE: use constants instead of passing config, better upgrade support. NOTE::: there is still much debugging in this version. It should not be used on production systems (though the logging will probably be stripped out soon enough). The basic problem is that the upgrade system (cs_webdbupgrade) depends upon the logger (cs_webdblogger) for logging, but the logger could potentially upgrade, as could the upgrade system: in the situation where the logger gets upgraded, bad things happen; when both get upgraded, worse things happen. One of the errors I experienced was that the system would get stuck in a loop until the database ran out of available connections. /cs_webdbupgrade.class.php: * MAIN::: -- temporarily include a script for cs_debug_backtrace() (debugging) -- new private var $internalUpgradeInProgress = false -- new private vars for log storage (still in progress of implementation here... there's chicken-or-the-egg issues happening between this class and cs_webdblogger). * __construct(): -- VAR CHANGE: RENAMED VAR: #2 ($upgradeConfigFile) -- VAR CHANGE: NEW VAR: $lockFile='upgrade.lock' -- Systems MUST send the location of their upgrade.xml file, their version file, and optionally specify the name of the lockfile (so only that given system is locked). -- use constants and passed parameters to build the internal config array instead of requiring that it be passed. -- NOTE::: setting $this->versionFileLocation creates a var for this class that is SEPARATE from the private one in cs_versionAbstract; one MUST call set_version_file_location() instead of trying to set it directly. -- The call to connect_logger() has no arguments so the default log category can be set in a standardized way. * CHANGE LOGGING (call do_log()):::: -- check_versions() -- perform_upgrade() -- do_single_upgrade() -- check_database_version() -- do_scripted_upgrade() -- get_upgrade_list() -- fix_xml_config() -- load_table() -- error_handler() -- load_initial_version() * do_scripted_upgrade(): -- the directory for upgrade scripts should ALWAYS be in the same place as the upgrade.xml file, so use that as the directory using dirname() and stop logging errors about it. * error_handler(): -- logic for handling the situation where logsObj isn't an object, with additional logic for if the system is currently undergoing an upgrade... -- NOTE::: doesthe "suspended logging" logic here actually probably fit better in cs_webdblogger's domain... ? * load_initial_version(): -- fix insert logic to match new database schema. * connect_logger(): -- ARG CHANGE: DEFAULT VALUE SET: $logCategory=null -- debugging -- logic for setting logCategory if none passed -- pass false as the 3rd arg to the pending version of webdblogger, to tell it NOT to look for upgrades... * do_log() [NEW]: -- method for handling logging. The idea here is to have a standardized way of logging, plus a place where logs can be temporarily suspended if they need to be (i.e. if the system itself is undergoing an upgrade). Modified Paths: -------------- trunk/0.1/cs_webdbupgrade.class.php Modified: trunk/0.1/cs_webdbupgrade.class.php =================================================================== --- trunk/0.1/cs_webdbupgrade.class.php 2009-08-07 15:51:14 UTC (rev 35) +++ trunk/0.1/cs_webdbupgrade.class.php 2009-08-11 18:51:07 UTC (rev 36) @@ -13,6 +13,7 @@ */ require_once(constant('LIBDIR') .'/cs-versionparse/cs_version.abstract.class.php'); +require_once(constant('LIBDIR') .'/cs_debug.php'); class cs_webdbupgrade extends cs_versionAbstract { @@ -46,9 +47,16 @@ /** Name (absolute location) of *.lock file that indicates an upgrade is running. */ private $lockfile; + /** Determines if an internal upgrade is happening (avoids some infinite loops) */ + private $internalUpgradeInProgress = false; + /** */ private $allowNoDBVersion=true; + /** Log messages to store during an internal upgrade (to avoid problems) */ + private $storedLogs = array(); + private $debugLogs=array(); + /** List of acceptable suffixes; example "1.0.0-BETA3" -- NOTE: these MUST be in * an order that reflects newest -> oldest; "ALPHA happens before BETA, etc. */ private $suffixList = array( @@ -58,34 +66,17 @@ ); //========================================================================= - public function __construct($versionFileLocation, array $config) { + public function __construct($versionFileLocation, $upgradeConfigFile, $lockFile='upgrade.lock') { - //Handle the config array (cope with XML-ish array) - if(is_array($config)) { - //check if it is in the complex XML array style... - $keys = array_keys($config); - if(isset($config[$keys[0]]['type'])) { - $this->fix_xml_config($config); - $this->config = $this->tempXmlConfig; - } - else { - $this->config = $config; - } - } - else { - throw new exception(__METHOD__ .": no configuration available"); - } - - //cope with problems in CS-Content v1.0-ALPHA9 (or before)--see http://project.crazedsanity.com/extern/helpdesk/view?ID=281 - if(isset($this->config['DBPARMLINKER'])) { - $this->config['DBPARAMS'] = array(); - foreach($this->config['DBPARMLINKER'] as $i=>$loc) { - $this->config['DBPARAMS'][strtolower($i)] = $this->config[$loc]; - unset($this->config[$loc]); - } - unset($this->config['DBPARMLINKER']); - } - + //setup configuration parameters for database connectivity. + $dbParams = array( + 'host' => constant(__CLASS__ .'-DB_CONNECT_HOST'), + 'port' => constant(__CLASS__ .'-DB_CONNECT_PORT'), + 'dbname' => constant(__CLASS__ .'-DB_CONNECT_DBNAME'), + 'user' => constant(__CLASS__ .'-DB_CONNECT_USER'), + 'password' => constant(__CLASS__ .'-DB_CONNECT_PASSWORD') + ); + $this->config['DBPARAMS'] = $dbParams; //Check for some required constants. $requisiteConstants = array('LIBDIR'); if(!defined('LIBDIR')) { @@ -103,32 +94,46 @@ require_once(constant('LIBDIR') .'/cs-phpxml/cs_phpxmlCreator.class.php'); require_once(constant('LIBDIR') .'/cs-phpxml/cs_arrayToPath.class.php'); - $this->versionFileLocation = $versionFileLocation; - $this->fsObj = new cs_fileSystem(constant('SITE_ROOT')); $this->gfObj = new cs_globalFunctions; if(defined('DEBUGPRINTOPT')) { $this->gfObj->debugPrintOpt = constant('DEBUGPRINTOPT'); } - if(!isset($this->config['DB_PRIMARYKEY']) || !isset($this->config['DB_TABLE'])) { + if(!defined(__CLASS__ .'-DB_PRIMARYKEY') || !defined(__CLASS__ .'-DB_TABLE')) { throw new exception(__METHOD__ .": no setting for DB_TABLE or DB_PRIMARYKEY, cannot continue"); } + else { + $this->config['DB_TABLE'] = constant(__CLASS__ .'-DB_TABLE'); + $this->config['DB_PRIMARYKEY'] = constant(__CLASS__ .'-DB_PRIMARYKEY'); + } $this->sequenceName = $this->config['DB_TABLE'] .'_'. $this->config['DB_PRIMARYKEY'] .'_seq'; if(!defined('DBTYPE')) { throw new exception(__METHOD__ .": required constant 'DBTYPE' not set"); } - if(!isset($this->config['CONFIG_FILE_LOCATION'])) { - throw new exception(__METHOD__ .": required setting 'CONFIG_FILE_LOCATION' not found"); + + if(!file_exists($upgradeConfigFile) || !is_readable($upgradeConfigFile)) { + throw new exception(__METHOD__ .": required upgrade config file location (". $upgradeConfigFile .") not set or unreadable"); } + else { + $this->config['UPGRADE_CONFIG_FILE'] = $upgradeConfigFile; + } if(!strlen($versionFileLocation) || !file_exists($versionFileLocation)) { throw new exception(__METHOD__ .": unable to locate version file (". $versionFileLocation .")"); } - if(!isset($this->config['RWDIR']) || !is_dir($this->config['RWDIR']) || !is_readable($this->config['RWDIR']) || !is_writable($this->config['RWDIR'])) { - throw new exception(__METHOD__ .": missing RWDIR (". $this->config['RWDIR'] .") or isn't readable/writable"); + $this->set_version_file_location($versionFileLocation); + + if(!defined(__CLASS__ .'-RWDIR') || !is_dir(constant(__CLASS__ .'-RWDIR')) || !is_readable(constant(__CLASS__ .'-RWDIR')) || !is_writable(constant(__CLASS__ .'-RWDIR'))) { + throw new exception(__METHOD__ .": missing RWDIR (". constant(__CLASS__ .'-RWDIR') .") or isn't readable/writable"); } - $this->lockfile = $this->config['RWDIR'] .'/upgrade.lock'; + else { + $this->config['RWDIR'] = constant(__CLASS__ .'-RWDIR'); + } + if(!is_string($lockFile)) { + $lockFile = 'upgrade.lock'; + } + $this->lockfile = $this->config['RWDIR'] .'/'. $lockFile; $this->db = new cs_phpDB(constant('DBTYPE')); try { @@ -140,17 +145,22 @@ if($this->check_lockfile()) { //there is an existing lockfile... - $this->error_handler(__METHOD__ .": upgrade in progress: ". $this->fsObj->read($this->lockfile)); + throw new exception(__METHOD__ .": upgrade in progress: ". $this->fsObj->read($this->lockfile)); } +$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); + $this->check_internal_upgrades(); + +$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); try { - $this->connect_logger("Upgrade"); + $this->connect_logger(); } catch(exception $e) { throw new exception(__METHOD__ .": failed to create logger::: ". $e->getMessage()); } + $this->gfObj->debug_print($this,1); $this->check_versions(false); }//end __construct() //========================================================================= @@ -162,45 +172,51 @@ * Determine if there are any upgrades that need to be performed... */ private function check_internal_upgrades() { +$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); $oldVersionFileLocation = $this->versionFileLocation; $oldUpgradeConfigFile = $this->config['UPGRADE_CONFIG_FILE']; $this->config['UPGRADE_CONFIG_FILE'] = dirname(__FILE__) .'/upgrades/upgrade.xml'; +$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); - //connect the logger... - try { - $this->connect_logger("Internal Upgrade"); - } - catch(exception $e) { - $this->error_handler($e->getMessage()); - } + //set a status flag so we can store log messages (for now). + $this->internalUpgradeInProgress = true; +$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); //do stuff here... - $this->versionFileLocation = dirname(__FILE__) .'/VERSION'; + $this->set_version_file_location(dirname(__FILE__) .'/VERSION'); $this->read_version_file(); +$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); //if there is an error, then... uh... yeah. try { $this->get_database_version(); } catch(exception $e) { - #throw new exception(__METHOD__ .": error while retrieving database version: ". $e->getMessage()); + throw new exception(__METHOD__ .": error while retrieving database version: ". $e->getMessage()); //try creating the version. $this->load_initial_version(); } //do upgrades here... +$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); $this->check_versions(true); +$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); + $this->internalUpgradeInProgress = false; +$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); //reset internal vars. - $this->versionFileLocation = $oldVersionFileLocation; + $this->set_version_file_location($oldVersionFileLocation); +$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); $this->config['UPGRADE_CONFIG_FILE'] = $oldUpgradeConfigFile; +$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); $this->read_version_file(); +$this->gfObj->debug_print(__METHOD__ .": line#". __LINE__ ." (". $this->projectName ." - ". $this->versionFileLocation .") -- CONFIG::: ". $this->gfObj->debug_print($this->config,0),1); }//end check_internal_upgrades() //========================================================================= @@ -223,7 +239,7 @@ //check to see if the lock files for upgrading exist. if($this->upgrade_in_progress()) { - $this->logsObj->log_by_class("Upgrade in progress", 'notice'); + $this->do_log("Upgrade in progress", 'notice'); throw new exception(__METHOD__ .": upgrade in progress"); } else { @@ -334,7 +350,7 @@ $lockConfig = $this->upgrade_in_progress(TRUE); $this->fsObj->cd("/"); - $this->logsObj->log_by_class("Starting upgrade process...", 'begin'); + $this->do_log("Starting upgrade process...", 'begin'); //TODO: not only should the "create_file()" method be run, but also do a sanity check by calling lock_file_exists(). if($lockConfig === 0) { @@ -342,7 +358,7 @@ $this->error_handler(__METHOD__ .": failed to set 'upgrade in progress'"); } else { - $this->logsObj->log_by_class(__METHOD__ .": result of creating lockfile: (". $lockConfig .")", 'debug'); + $this->do_log(__METHOD__ .": result of creating lockfile: (". $lockConfig .")", 'debug'); //push data into our internal "config" array. $this->read_upgrade_config_file(); @@ -353,39 +369,38 @@ if($versionConflictInfo !== false) { - $this->logsObj->log_by_class("Upgrading ". $versionConflictInfo ." versions, from " . + $this->do_log("Upgrading ". $versionConflictInfo ." versions, from " . "(". $this->databaseVersion .") to (". $this->versionFileVersion .")", 'info'); } $upgradeList = $this->get_upgrade_list(); - try { $i=0; - $this->logsObj->log_by_class(__METHOD__ .": starting to run through the upgrade list, starting at (". $this->databaseVersion ."), " . + $this->do_log(__METHOD__ .": starting to run through the upgrade list, starting at (". $this->databaseVersion ."), " . "total number of upgrades to perform: ". count($upgradeList), 'debug'); $this->db->beginTrans(__METHOD__); foreach($upgradeList as $fromVersion=>$toVersion) { $details = __METHOD__ .": upgrading from ". $fromVersion ." to ". $toVersion ."... "; - $this->logsObj->log_by_class($details, 'system'); + $this->do_log($details, 'system'); $this->do_single_upgrade($fromVersion, $toVersion); $this->get_database_version(); $i++; $details = __METHOD__ .": finished upgrade #". $i .", now at version (". $this->databaseVersion .")"; - $this->logsObj->log_by_class($details, 'system'); + $this->do_log($details, 'system'); } if($i < count($upgradeList)) { - $this->logsObj->log_by_class(__METHOD__ .": completed upgrade ". $i ." of ". count($upgradeList), 'debug'); + $this->do_log(__METHOD__ .": completed upgrade ". $i ." of ". count($upgradeList), 'debug'); } else { if($this->databaseVersion == $this->versionFileVersion) { - $this->logsObj->log_by_class(__METHOD__ .": finished upgrading after performing (". $i .") upgrades", 'debug'); + $this->do_log(__METHOD__ .": finished upgrading after performing (". $i .") upgrades", 'debug'); $this->newVersion = $this->databaseVersion; } else { - $this->logsObj->log_by_class(__METHOD__ .": upgradeList::: ". $this->gfObj->debug_print($upgradeList,0), 'debug'); + $this->do_log(__METHOD__ .": upgradeList::: ". $this->gfObj->debug_print($upgradeList,0), 'debug'); $this->error_handler(__METHOD__ .": finished upgrade, but version wasn't updated (expecting '". $this->versionFileVersion ."', got '". $this->databaseVersion ."')!!!"); } } @@ -397,7 +412,7 @@ $this->error_handler(__METHOD__ .": upgrade aborted:::". $e->getMessage()); $this->db->rollbackTrans(); } - $this->logsObj->log_by_class("Upgrade process complete", 'end'); + $this->do_log("Upgrade process complete", 'end'); } } }//end perform_upgrade() @@ -607,7 +622,7 @@ $this->error_handler(__METHOD__ .": target version not specified, unable to proceed with upgrade for ". $versionIndex); } } - $this->logsObj->log_by_class("Finished upgrade to ". $this->newVersion, 'system'); + $this->do_log("Finished upgrade to ". $this->newVersion, 'system'); }//end do_single_upgrade() //========================================================================= @@ -666,7 +681,7 @@ } if(!$retval) { - $this->logsObj->log_by_class("Version check failed, versionString=(". $versionString ."), checkVersion=(". $this->newVersion .")", 'FATAL'); + $this->do_log("Version check failed, versionString=(". $versionString ."), checkVersion=(". $this->newVersion .")", 'FATAL'); } } @@ -684,20 +699,16 @@ private function do_scripted_upgrade(array $upgradeData) { $myConfigFile = $upgradeData['SCRIPT_NAME']; - $this->logsObj->log_by_class("Preparing to run script '". $myConfigFile ."'", 'debug'); + $this->do_log("Preparing to run script '". $myConfigFile ."'", 'debug'); //we've got the filename, see if it exists. - if(isset($this->config['UPGRADE_SCRIPTS_DIR'])) { - $scriptsDir = $this->config['UPGRADE_SCRIPTS_DIR']; - } - else { - $this->logsObj->log_by_class("No UPGRADE_SCRIPTS_DIR config setting", 'warning'); - $scriptsDir = dirname($this->config['UPGRADE_CONFIG_FILE']); - } + + $scriptsDir = dirname($this->config['UPGRADE_CONFIG_FILE']); $fileName = $scriptsDir .'/'. $myConfigFile; + if(file_exists($fileName)) { - - $this->logsObj->log_by_class("Performing scripted upgrade (". $myConfigFile .")", 'DEBUG'); + + $this->do_log("(". __CLASS__ .") Performing scripted upgrade (". $myConfigFile .") from file '". $fileName ."'", 'DEBUG'); $createClassName = $upgradeData['CLASS_NAME']; $classUpgradeMethod = $upgradeData['CALL_METHOD']; require_once($fileName); @@ -710,12 +721,12 @@ if($upgradeResult === true) { //yay, it worked! - $this->logsObj->log_by_class("Upgrade succeeded (". $upgradeResult .")", 'success'); + $this->do_log("Upgrade succeeded (". $upgradeResult .")", 'success'); } else { $this->error_handler(__METHOD__ .": upgrade failed (". $upgradeResult .")"); } - $this->logsObj->log_by_class("Finished running ". $createClassName ."::". $classUpgradeMethod ."(), result was (". $upgradeResult .")", 'debug'); + $this->do_log("Finished running ". $createClassName ."::". $classUpgradeMethod ."(), result was (". $upgradeResult .")", 'debug'); } else { $this->error_handler(__METHOD__ .": upgrade method doesn't exist (". $createClassName ."::". $classUpgradeMethod @@ -788,11 +799,11 @@ $retval[$matchVersion] = $data['TARGET_VERSION']; } else { - $this->logsObj->log_by_class(__METHOD__ .": entry in upgrade.xml (". $matchVersion .") is higher than the VERSION file (". $this->versionFileVersion .")", 'warning'); + $this->do_log(__METHOD__ .": entry in upgrade.xml (". $matchVersion .") is higher than the VERSION file (". $this->versionFileVersion .")", 'warning'); } } else { - $this->logsObj->log_by_class(__METHOD__ .": SKIPPING (". $matchVersion .")", 'debug'); + $this->do_log(__METHOD__ .": SKIPPING (". $matchVersion .")", 'debug'); } } @@ -802,7 +813,7 @@ } else { //no intermediary upgrades: just pass back the latest version. - $this->logsObj->log_by_class(__METHOD__ .": no intermediary upgrades", 'debug'); + $this->do_log(__METHOD__ .": no intermediary upgrades", 'debug'); $retval[$dbVersion] = $this->versionFileVersion; } @@ -856,7 +867,7 @@ $a2p = new cs_arrayToPath($config); } catch(exception $e) { - $this->logsObj->log_by_class(__METHOD__ .': encountered exception: '. $e->getMessage()); + $this->do_log(__METHOD__ .': encountered exception: '. $e->getMessage()); $this->error_handler($e->getMessage()); } if(!is_array($this->tempXmlConfig)) { @@ -866,7 +877,7 @@ $myA2p = new cs_arrayToPath(&$this->tempXmlConfig); } catch(exception $e) { - $this->logsObj->log_by_class(__METHOD__ .': encountered exception: '. $e->getMessage()); + $this->do_log(__METHOD__ .': encountered exception: '. $e->getMessage()); $this->error_handler($e->getMessage()); } @@ -930,7 +941,7 @@ $logRes = 'Failed to load'; $logType = 'error'; } - $this->logsObj->log_by_class($logRes .' table ('. $this->config['DB_TABLE'] .') into ' . + $this->do_log($logRes .' table ('. $this->config['DB_TABLE'] .') into ' . 'database::: '. $loadTableResult, $logType); return($loadTableResult); @@ -1026,7 +1037,18 @@ //========================================================================= public function error_handler($details) { //log the error. - $this->logsObj->log_by_class($details, 'exception in code'); + $this->gfObj->debug_print($this->debugLogs,1); + if(!is_object($this->logsObj)) { + if($this->internalUpgradeInProgress === true) { + throw new exception(__METHOD__ .": error while running an internal upgrade::: ". $details); + } + else { + $this->connect_logger(); + } + } + if($this->internalUpgradeInProgress === false) { + $this->do_log($details, 'exception in code'); + } //now throw an exception so other code can catch it. throw new exception($details); @@ -1039,19 +1061,24 @@ public function load_initial_version() { //if there's an INITIAL_VERSION in the upgrade config file, use that. $this->read_upgrade_config_file(); + $insertData = array(); if(isset($this->config['UPGRADELIST']['INITIALVERSION'])) { - $insertData = $this->parse_version_string($this->config['UPGRADELIST']['INITIALVERSION']); + $parseThis = $this->config['UPGRADELIST']['INITIALVERSION']; } else { - $insertData = $this->parse_version_string($this->versionFileVersion); + $parseThis = $this->versionFileVersion; } - $insertData['project_name'] = $this->projectName; + $versionInfo = $this->parse_version_string($parseThis); + $insertData = array( + 'project_name' => $this->projectName, + 'version_string' => $versionInfo['version_string'] + ); $sql = 'INSERT INTO '. $this->config['DB_TABLE'] . $this->gfObj->string_from_array($insertData, 'insert'); if($this->db->run_insert($sql, $this->sequenceName)) { $loadRes = true; - $this->logsObj->log_by_class("Created data for '". $this->projectName ."' with version '". $insertData['version_string'] ."'", 'initialize'); + $this->do_log("Created data for '". $this->projectName ."' with version '". $insertData['version_string'] ."'", 'initialize'); } else { $this->error_handler(__METHOD__ .": failed to load initial version::: ". $e->getMessage()); @@ -1064,14 +1091,35 @@ //========================================================================= - private function connect_logger($logCategory) { + private function connect_logger($logCategory=null) { + + cs_debug_backtrace(1); + + if(is_null($logCategory) || !strlen($logCategory)) { + $logCategory = "Upgrade ". $this->projectName; + } + $loggerDb = new cs_phpDB(constant('DBTYPE')); $loggerDb->connect($this->config['DBPARAMS'], true); - $this->logsObj = new cs_webdblogger($loggerDb, $logCategory); + $this->logsObj = new cs_webdblogger($loggerDb, $logCategory, false); }//end connect_logger() //========================================================================= + + //========================================================================= + protected function do_log($message, $type) { + $this->debugLogs[] = array('project'=>$this->projectName,'upgradeFile'=>$this->config['UPGRADE_CONFIG_FILE'],'message'=>$message,'type'=>$type); + if($this->internalUpgradeInProgress === true) { + $this->storedLogs[] = func_get_args(); + } + else { + $this->logsObj->log_by_class($message, $type); + } + }//end do_log() + //========================================================================= + + }//end upgrade{} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-08-07 15:51:23
|
Revision: 35 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=35&view=rev Author: crazedsanity Date: 2009-08-07 15:51:14 +0000 (Fri, 07 Aug 2009) Log Message: ----------- *** RELEASE 0.2.0 *** This is the first fully functional release since inception, so there is no real clear-cut place where 0.1 ended and 0.2 started. This changelog therefore will basically be all-inclusive. SUMMARY OF CHANGES::: * automatically load table into the database on first use. * create full version string from shorthand properly (i.e. 1.2.0 from 1.2) * uses lockfile instead of modifying site's XML config (could get destroyed) * fixes for multiple inline scripted + version-only upgrades * added logging (requires cs-content + cs-webdblogger) * MySQL compatibility fixes + notes on implicit commits :( * option for INITIALVERSION setting so upgrades can run on first use * ability to do internal upgrades (+ scripts for upgrading from 0.1.x) * minimal version data stored in database (just version string, no parts) Added Paths: ----------- releases/0.2/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-08-07 15:46:04
|
Revision: 34 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=34&view=rev Author: crazedsanity Date: 2009-08-07 15:45:55 +0000 (Fri, 07 Aug 2009) Log Message: ----------- *** RELEASE 0.2.0 *** This is the first fully functional release since inception, so there is no real clear-cut place where 0.1 ended and 0.2 started. This changelog therefore will basically be all-inclusive. SUMMARY OF CHANGES::: * automatically load table into the database on first use. * create full version string from shorthand properly (i.e. 1.2.0 from 1.2) * uses lockfile instead of modifying site's XML config (could get destroyed) * fixes for multiple inline scripted + version-only upgrades * added logging (requires cs-content + cs-webdblogger) * MySQL compatibility fixes + notes on implicit commits :( * option for INITIALVERSION setting so upgrades can run on first use * ability to do internal upgrades (+ scripts for upgrading from 0.1.x) * minimal version data stored in database (just version string, no parts) Modified Paths: -------------- trunk/0.2/VERSION Modified: trunk/0.2/VERSION =================================================================== --- trunk/0.2/VERSION 2009-08-07 14:48:39 UTC (rev 33) +++ trunk/0.2/VERSION 2009-08-07 15:45:55 UTC (rev 34) @@ -1,6 +1,6 @@ ## Stores the current version of the cs-versionparse system, and it's source. ## Please do NOT modify this file. -VERSION: 0.2 +VERSION: 0.2.0 PROJECT: cs-webdbupgrade $HeadURL$ \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-08-07 14:48:48
|
Revision: 33 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=33&view=rev Author: crazedsanity Date: 2009-08-07 14:48:39 +0000 (Fri, 07 Aug 2009) Log Message: ----------- Version 0.2.x... note that 0.1.x contained everything for upgrading to 0.2.x... Added Paths: ----------- trunk/0.2/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-08-06 20:51:56
|
Revision: 32 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=32&view=rev Author: crazedsanity Date: 2009-08-06 20:51:45 +0000 (Thu, 06 Aug 2009) Log Message: ----------- Changes to go along with the v0.2 release. /cs_webdbupgrade.class.php: * update_database_version(): -- only update the version_string field: v0.2 no longer has the "pieces" columns (version_major, version_minor, etc). Modified Paths: -------------- trunk/0.1/cs_webdbupgrade.class.php Modified: trunk/0.1/cs_webdbupgrade.class.php =================================================================== --- trunk/0.1/cs_webdbupgrade.class.php 2009-08-06 20:45:38 UTC (rev 31) +++ trunk/0.1/cs_webdbupgrade.class.php 2009-08-06 20:51:45 UTC (rev 32) @@ -619,19 +619,14 @@ * so the version there is consistent with all the others. */ protected function update_database_version($newVersionString) { - $versionArr = $this->parse_version_string($newVersionString); + $versionInfo = $this->parse_version_string($newVersionString); - $queryArr = array(); - foreach($versionArr as $index=>$value) { - $queryArr[$index] = "SELECT internal_data_set_value('". $index ."', '". $value ."');"; - } + $sql = "UPDATE ". $this->config['DB_TABLE'] ." SET version_string='". + $this->gfObj->cleanString($versionInfo['version_string'], 'sql') + ."' WHERE project_name='". + $this->gfObj->cleanString($this->projectName, 'sql') ."'"; - $updateData = $versionArr; - $sql = "UPDATE ". $this->config['DB_TABLE'] ." SET ". - $this->gfObj->string_from_array($updateData, 'update', null, 'sql') ." WHERE " . - "project_name='". $this->gfObj->cleanString($this->projectName, 'sql') ."'"; - $updateRes = $this->db->run_update($sql,false); if($updateRes == 1) { $retval = $updateRes; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-08-06 20:45:47
|
Revision: 31 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=31&view=rev Author: crazedsanity Date: 2009-08-06 20:45:38 +0000 (Thu, 06 Aug 2009) Log Message: ----------- Upgrade scripts & schema. Modified Paths: -------------- trunk/0.1/schema/schema.sql Added Paths: ----------- trunk/0.1/upgrades/ trunk/0.1/upgrades/upgrade.xml trunk/0.1/upgrades/upgradeTo0.2.0.php Modified: trunk/0.1/schema/schema.sql =================================================================== --- trunk/0.1/schema/schema.sql 2009-08-06 20:44:19 UTC (rev 30) +++ trunk/0.1/schema/schema.sql 2009-08-06 20:45:38 UTC (rev 31) @@ -15,7 +15,7 @@ -- "DB_TABLE" setting. CREATE TABLE {tableName} ( {primaryKey} serial NOT NULL PRIMARY KEY, - project_name varchar(30) NOT NULL, + project_name varchar(30) NOT NULL UNIQUE, version_string varchar(50) NOT NULL, version_major integer NOT NULL, version_minor integer NOT NULL, Copied: trunk/0.1/upgrades/upgrade.xml (from rev 23, trunk/0.1/exampleUpgrades/upgrade.xml) =================================================================== --- trunk/0.1/upgrades/upgrade.xml (rev 0) +++ trunk/0.1/upgrades/upgrade.xml 2009-08-06 20:45:38 UTC (rev 31) @@ -0,0 +1,30 @@ +<upgrade> + <system_note>To determine which section in matching to use, heed only the information + beneath the tag that indicates the current database version (for 5.2.4, + you would find information under matching for "v5.2.4"). This section + indicates the version that it should upgrade the database to + ("target_version"), the name of the script ("script_name"), the class name + ("class_name"), and the name of the method within that class ("call_method") + to call in order to perform the upgrade. The method should return TRUE on + success: anything else would indicate failure. Upgrade failure may leave + the system in an inconsistent state. + + IMPORTANT: in order to facilitate doing multiple version upgrades, the name + of the class must be UNIQUE to all the other classes. For this reason, the + class name should be something like "v1_0_0_ALPHA1__to__v1_0_0_ALPHA2". + + REMEMBER: the "target_version" should NEVER be higher than the next item + beneath matching; this will cause horrible logic errors, causing an upgsrade + to get skipped, or an exception to be thrown, potentially leaving the system + in an unstable state. Unstable is bad, m'kay?</system_note> + + <initialversion>0.1.0</initialversion> + <matching> + <v0.1.0> + <target_version>0.2.0</target_version> + <script_name>upgradeTo0.2.0.php</script_name> + <class_name>upgrade_to_0_2_0</class_name> + <call_method>run_upgrade</call_method> + </v0.1.0> + </matching> +</upgrade> Copied: trunk/0.1/upgrades/upgradeTo0.2.0.php (from rev 23, trunk/0.1/exampleUpgrades/upgradeTo1.2.0-ALPHA4.php) =================================================================== --- trunk/0.1/upgrades/upgradeTo0.2.0.php (rev 0) +++ trunk/0.1/upgrades/upgradeTo0.2.0.php 2009-08-06 20:45:38 UTC (rev 31) @@ -0,0 +1,52 @@ +<?php + +class upgrade_to_0_2_0 extends cs_webdbupgrade { + + //========================================================================= + public function __construct(cs_phpDB &$db) { + if(!$db->is_connected()) { + throw new exception(__METHOD__ .": database is not connected"); + } + $this->db = $db; + + $this->gfObj = new cs_globalFunctions; + $this->gfObj->debugPrintOpt = 1; + + //make sure there's enough info to use. + $requiredConstants = array( + 'table' => 'cs_webdbupgrade-DB_TABLE', + 'pkey' => 'cs_webdbupgrade-DB_PRIMARYKEY', + 'seq' => 'cs_webdbupgrade-DB_SEQUENCE' + ); + + $this->dbStuff = array(); + foreach($requiredConstants as $k=>$v) { + if(defined($v)) { + $this->dbStuff[$k] = constant($v); + } + else { + throw new exception(__METHOD__ .": missing required constant (". $v .")"); + } + } + + + }//end __construct() + //========================================================================= + + + + //========================================================================= + public function run_upgrade() { + + $dropColumns = array('version_major', 'version_minor', 'version_maintenance', 'version_suffix'); + foreach($dropColumns as $col) { + $sql = "ALTER TABLE ". $this->dbStuff['table'] ." DROP COLUMN ". $col; + $this->db->run_update($sql, true); + } + + return(true); + }//end run_upgrade() + //========================================================================= +} + +?> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-08-06 20:44:28
|
Revision: 30 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=30&view=rev Author: crazedsanity Date: 2009-08-06 20:44:19 +0000 (Thu, 06 Aug 2009) Log Message: ----------- Moved some files into "docs" subdirectory for cleanliness. Modified Paths: -------------- trunk/0.1/VERSION Added Paths: ----------- trunk/0.1/docs/ trunk/0.1/docs/CREDITS trunk/0.1/docs/LICENSE trunk/0.1/docs/README.txt trunk/0.1/docs/SETUP.txt Removed Paths: ------------- trunk/0.1/CREDITS trunk/0.1/LICENSE trunk/0.1/README.txt Deleted: trunk/0.1/CREDITS =================================================================== --- trunk/0.1/CREDITS 2009-08-06 19:22:43 UTC (rev 29) +++ trunk/0.1/CREDITS 2009-08-06 20:44:19 UTC (rev 30) @@ -1,3 +0,0 @@ - -Lead Developer: Dan Falconer (cra...@us...) - Deleted: trunk/0.1/LICENSE =================================================================== --- trunk/0.1/LICENSE 2009-08-06 19:22:43 UTC (rev 29) +++ trunk/0.1/LICENSE 2009-08-06 20:44:19 UTC (rev 30) @@ -1,291 +0,0 @@ -NOTE: a full HTML version of this license can be found at: -http://www.opensource.org/licenses/gpl-license.php - -It has been reproduced below without any HTML. -========================================================================== - -The GNU General Public License (GPL) - -Version 2, June 1991 - - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - -NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS Deleted: trunk/0.1/README.txt =================================================================== --- trunk/0.1/README.txt 2009-08-06 19:22:43 UTC (rev 29) +++ trunk/0.1/README.txt 2009-08-06 20:44:19 UTC (rev 30) @@ -1,60 +0,0 @@ - -$Id$ - -This system is built to make upgrading a database-driven app seamless. No need -to coordinate SQL or schema changes with the code updates: previously, one would -have to take the entire website down, run the schema/SQL change, update the code, -and (if you're lucky) check a "test" website to ensure it works before unleashing -it upon your users.... if you're unlucky, they both must be run in unison, and -if the SQL or schema change fails, you're in for a lot of sweating and praying. - -Meet your saviour! This system adds the ability to allow your system to upgrade -itself. Whenever you increment the version in your VERSION file, it can run a -custom script that will do everything you need AND keep others out until it is -done. Once the system is updated, the next thing to touch the code containing -the upgrade system will cause it to run. - -CAVEATS: while this system will work with MySQL, I **STRONGLY** recommend -against it. It was built using PostgreSQL, which has a rock solid transaction -system: if the upgrade fails, everything rolls-back and it is up to a developer -to figure out what went wrong--but the system is left in a CONSISTENT STATE. -With MySQL, this will only work with InnoDB tables--and only if ALL AFFECTED -TABLES ARE InnoDB. There are also many things that will cause an implicit -commit, meaning the code will think its in a transaction after that point, but -it actually isn't (which is possibly worse than not having transactional -capabilities at all). - -The first time this system is implemented, you need to be aware that it will -look for an "INITIALVERSION" value in your upgrade.xml file. This version -determines where it should start, so intermediary upgrade scripts will run. It -is important to realize, however, that this setting can cause grief in and of -itself: if you give the wrong version, scripts might run that shouldn't. This -is especially important for long-running projects that are expected to be able -to be installed at any version: subsequent releases should update this initial -version (or remove it) as necessary. - -MySQL TRANSACTION INFO::: http://dev.mysql.com/doc/refman/5.0/en/implicit-commit.html - -WORK FLOW: - - --> Is there an existing LOCK file? - YES:: - --> HALT (tell the user there's an upgrade in progress). - NO::: - --> System checks VERSION file vs. version in database - --> Does version file's version match database version? - YES::: - -- good to go. - -- CONTINUE - NO::: - --> CREATE LOCK FILE - --> find named script in upgrade.xml file - --> include script, create new class, call method (in upgrade.xml file) - --> did upgrade succeed? - YES::: - --> remove LOCK file - --> CONTINUE - NO::: - --> stop upgrade process. - --> HALT - --> (continues as before) \ No newline at end of file Modified: trunk/0.1/VERSION =================================================================== --- trunk/0.1/VERSION 2009-08-06 19:22:43 UTC (rev 29) +++ trunk/0.1/VERSION 2009-08-06 20:44:19 UTC (rev 30) @@ -1,6 +1,6 @@ ## Stores the current version of the cs-versionparse system, and it's source. ## Please do NOT modify this file. -VERSION: 0.1 +VERSION: 0.2 PROJECT: cs-webdbupgrade $HeadURL$ \ No newline at end of file Copied: trunk/0.1/docs/CREDITS (from rev 26, trunk/0.1/CREDITS) =================================================================== --- trunk/0.1/docs/CREDITS (rev 0) +++ trunk/0.1/docs/CREDITS 2009-08-06 20:44:19 UTC (rev 30) @@ -0,0 +1,3 @@ + +Lead Developer: Dan Falconer (cra...@us...) + Copied: trunk/0.1/docs/LICENSE (from rev 26, trunk/0.1/LICENSE) =================================================================== --- trunk/0.1/docs/LICENSE (rev 0) +++ trunk/0.1/docs/LICENSE 2009-08-06 20:44:19 UTC (rev 30) @@ -0,0 +1,291 @@ +NOTE: a full HTML version of this license can be found at: +http://www.opensource.org/licenses/gpl-license.php + +It has been reproduced below without any HTML. +========================================================================== + +The GNU General Public License (GPL) + +Version 2, June 1991 + + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + +NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS Copied: trunk/0.1/docs/README.txt (from rev 28, trunk/0.1/README.txt) =================================================================== --- trunk/0.1/docs/README.txt (rev 0) +++ trunk/0.1/docs/README.txt 2009-08-06 20:44:19 UTC (rev 30) @@ -0,0 +1,60 @@ + +$Id$ + +This system is built to make upgrading a database-driven app seamless. No need +to coordinate SQL or schema changes with the code updates: previously, one would +have to take the entire website down, run the schema/SQL change, update the code, +and (if you're lucky) check a "test" website to ensure it works before unleashing +it upon your users.... if you're unlucky, they both must be run in unison, and +if the SQL or schema change fails, you're in for a lot of sweating and praying. + +Meet your saviour! This system adds the ability to allow your system to upgrade +itself. Whenever you increment the version in your VERSION file, it can run a +custom script that will do everything you need AND keep others out until it is +done. Once the system is updated, the next thing to touch the code containing +the upgrade system will cause it to run. + +CAVEATS: while this system will work with MySQL, I **STRONGLY** recommend +against it. It was built using PostgreSQL, which has a rock solid transaction +system: if the upgrade fails, everything rolls-back and it is up to a developer +to figure out what went wrong--but the system is left in a CONSISTENT STATE. +With MySQL, this will only work with InnoDB tables--and only if ALL AFFECTED +TABLES ARE InnoDB. There are also many things that will cause an implicit +commit, meaning the code will think its in a transaction after that point, but +it actually isn't (which is possibly worse than not having transactional +capabilities at all). + +The first time this system is implemented, you need to be aware that it will +look for an "INITIALVERSION" value in your upgrade.xml file. This version +determines where it should start, so intermediary upgrade scripts will run. It +is important to realize, however, that this setting can cause grief in and of +itself: if you give the wrong version, scripts might run that shouldn't. This +is especially important for long-running projects that are expected to be able +to be installed at any version: subsequent releases should update this initial +version (or remove it) as necessary. + +MySQL TRANSACTION INFO::: http://dev.mysql.com/doc/refman/5.0/en/implicit-commit.html + +WORK FLOW: + + --> Is there an existing LOCK file? + YES:: + --> HALT (tell the user there's an upgrade in progress). + NO::: + --> System checks VERSION file vs. version in database + --> Does version file's version match database version? + YES::: + -- good to go. + -- CONTINUE + NO::: + --> CREATE LOCK FILE + --> find named script in upgrade.xml file + --> include script, create new class, call method (in upgrade.xml file) + --> did upgrade succeed? + YES::: + --> remove LOCK file + --> CONTINUE + NO::: + --> stop upgrade process. + --> HALT + --> (continues as before) \ No newline at end of file Copied: trunk/0.1/docs/SETUP.txt (from rev 28, trunk/0.1/README.txt) =================================================================== --- trunk/0.1/docs/SETUP.txt (rev 0) +++ trunk/0.1/docs/SETUP.txt 2009-08-06 20:44:19 UTC (rev 30) @@ -0,0 +1,42 @@ + +$Id$ + +For information on how the system works, some caveats, and other useful +information, check out the "README.txt" in this folder. + +This system assumes that your website uses constants +(i.e. define('CONSTANTNAME', "constantValue")). It uses a couple of these +constants for the purposes of upgrading and so forth; if you would like an easy +way to put all your configuration stuff into one file and be able to set them +as global, constants, or both, look into using the "cs_siteConfig" library +provided by the latest version of CS-Content (see +"http://crazedsanity.com/projects/cs-content" for more information). For the +purposes of keeping this document as simple as possible, I will assume you've +set that system up (look at the afore-mentioned website for information on how +to interpret the XML below, and why I recommend using it). + +FOR CS-SITECONFIG: + +Add a section similar to the following: + + <cs-webupgradedb> + <dbparmlinker note="This compensates for cs_siteConfig::parse_config()'s inability to parse + 'template vars' past a certain depth in or before CS-Content v1.0-ALPHA9"> + <host>DB_CONNECT_HOST</host> + <dbname>DB_CONNECT_DBNAME</dbname> + <user>DB_CONNECT_USER</user> + <password>DB_CONNECT_PASSWORD</password> + <port>DB_CONNECT_PORT</port> + </dbparmlinker> + <db_table setconstant="1" setconstantprefix="cs_webdbupgrade">cs_version_table</db_table> + <db_primarykey setconstant="1" setconstantprefix="cs_webdbupgrade">project_id</db_primarykey> + <db_sequence setconstant="1" setconstantprefix="cs_webdbupgrade">{DB_TABLE}_{DB_PRIMARYKEY}_seq</db_sequence> + <db_connect_host>{/WEBSITE/DB_PG_HOST}</db_connect_host> + <db_connect_port>{/WEBSITE/DB_PG_PORT}</db_connect_port> + <db_connect_dbname>{WEBSITE/DB_PG_DBNAME}</db_connect_dbname> + <db_connect_user>{WEBSITE/DB_PG_DBUSER}</db_connect_user> + <db_connect_password>{WEBSITE/DB_PG_DBPASS}</db_connect_password> + <CONFIG_FILE_LOCATION>{_CONFIGFILE_}</CONFIG_FILE_LOCATION> + <UPGRADE_CONFIG_FILE>{SITE_ROOT}/upgrade/upgrade.xml</UPGRADE_CONFIG_FILE> + <RWDIR setconstant="1">{SITE_ROOT}/rw</RWDIR> + </cs-webupgradedb> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-08-06 19:22:54
|
Revision: 29 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=29&view=rev Author: crazedsanity Date: 2009-08-06 19:22:43 +0000 (Thu, 06 Aug 2009) Log Message: ----------- Drop example upgrades: there are now REAL upgrade scripts in the "upgrades" folder. Removed Paths: ------------- trunk/0.1/exampleUpgrades/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-08-06 14:53:23
|
Revision: 28 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=28&view=rev Author: crazedsanity Date: 2009-08-06 14:53:12 +0000 (Thu, 06 Aug 2009) Log Message: ----------- Fix typo. Modified Paths: -------------- trunk/0.1/README.txt Modified: trunk/0.1/README.txt =================================================================== --- trunk/0.1/README.txt 2009-08-06 14:48:20 UTC (rev 27) +++ trunk/0.1/README.txt 2009-08-06 14:53:12 UTC (rev 28) @@ -25,7 +25,7 @@ capabilities at all). The first time this system is implemented, you need to be aware that it will -look for an "INITIAL_VERSION" value in your upgrade.xml file. This version +look for an "INITIALVERSION" value in your upgrade.xml file. This version determines where it should start, so intermediary upgrade scripts will run. It is important to realize, however, that this setting can cause grief in and of itself: if you give the wrong version, scripts might run that shouldn't. This This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-08-06 14:48:37
|
Revision: 27 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=27&view=rev Author: crazedsanity Date: 2009-08-06 14:48:20 +0000 (Thu, 06 Aug 2009) Log Message: ----------- Slightly updated documentation regarding the INITIALVERSION. Modified Paths: -------------- trunk/0.1/README.txt Modified: trunk/0.1/README.txt =================================================================== --- trunk/0.1/README.txt 2009-08-04 20:33:29 UTC (rev 26) +++ trunk/0.1/README.txt 2009-08-06 14:48:20 UTC (rev 27) @@ -1,7 +1,7 @@ $Id$ -This system is built to make upgrading a database-driven app seemless. No need +This system is built to make upgrading a database-driven app seamless. No need to coordinate SQL or schema changes with the code updates: previously, one would have to take the entire website down, run the schema/SQL change, update the code, and (if you're lucky) check a "test" website to ensure it works before unleashing @@ -24,6 +24,15 @@ it actually isn't (which is possibly worse than not having transactional capabilities at all). +The first time this system is implemented, you need to be aware that it will +look for an "INITIAL_VERSION" value in your upgrade.xml file. This version +determines where it should start, so intermediary upgrade scripts will run. It +is important to realize, however, that this setting can cause grief in and of +itself: if you give the wrong version, scripts might run that shouldn't. This +is especially important for long-running projects that are expected to be able +to be installed at any version: subsequent releases should update this initial +version (or remove it) as necessary. + MySQL TRANSACTION INFO::: http://dev.mysql.com/doc/refman/5.0/en/implicit-commit.html WORK FLOW: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-08-04 20:33:44
|
Revision: 26 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=26&view=rev Author: crazedsanity Date: 2009-08-04 20:33:29 +0000 (Tue, 04 Aug 2009) Log Message: ----------- Better logging, internal upgrades "work", removed debugging. /cs_webdbupgrade.class.php: * __construct(): -- connect the logger AFTER calling check_internal_upgrades() -- call connect_logger(): this switches the category. * check_internal_upgrades(): -- connects logger with "Internal Upgrades" category -- removed a debug_print(). -- call check_versions(true) without errors! * load_initial_version(): -- removed a debug_print() * connect_db_logger() [NEW]: -- creates the internal cs_webdblogger{} object with the given category (basically, this is called to switch logged category). Modified Paths: -------------- trunk/0.1/cs_webdbupgrade.class.php Modified: trunk/0.1/cs_webdbupgrade.class.php =================================================================== --- trunk/0.1/cs_webdbupgrade.class.php 2009-08-04 18:59:26 UTC (rev 25) +++ trunk/0.1/cs_webdbupgrade.class.php 2009-08-04 20:33:29 UTC (rev 26) @@ -133,13 +133,8 @@ $this->db = new cs_phpDB(constant('DBTYPE')); try { $this->db->connect($this->config['DBPARAMS']); - - $loggerDb = new cs_phpDB(constant('DBTYPE')); - $loggerDb->connect($this->config['DBPARAMS'], true); - $this->logsObj = new cs_webdblogger($loggerDb, "Upgrade"); } catch(exception $e) { - $this->gfObj->debug_print($this->config,1); throw new exception(__METHOD__ .": failed to connect to database or logger error: ". $e->getMessage()); } @@ -149,6 +144,12 @@ } $this->check_internal_upgrades(); + try { + $this->connect_logger("Upgrade"); + } + catch(exception $e) { + throw new exception(__METHOD__ .": failed to create logger::: ". $e->getMessage()); + } $this->check_versions(false); }//end __construct() @@ -165,12 +166,20 @@ $oldUpgradeConfigFile = $this->config['UPGRADE_CONFIG_FILE']; $this->config['UPGRADE_CONFIG_FILE'] = dirname(__FILE__) .'/upgrades/upgrade.xml'; + + //connect the logger... + try { + $this->connect_logger("Internal Upgrade"); + } + catch(exception $e) { + $this->error_handler($e->getMessage()); + } + + //do stuff here... $this->versionFileLocation = dirname(__FILE__) .'/VERSION'; $this->read_version_file(); - $this->gfObj->debug_print($this->parse_version_string($this->versionFileVersion),1); - //if there is an error, then... uh... yeah. try { $this->get_database_version(); @@ -182,6 +191,12 @@ $this->load_initial_version(); } + //do upgrades here... + $this->check_versions(true); + + + + //reset internal vars. $this->versionFileLocation = $oldVersionFileLocation; $this->config['UPGRADE_CONFIG_FILE'] = $oldUpgradeConfigFile; @@ -1039,7 +1054,6 @@ $sql = 'INSERT INTO '. $this->config['DB_TABLE'] . $this->gfObj->string_from_array($insertData, 'insert'); - $this->gfObj->debug_print(__METHOD__ .": SQL::: ". $sql,1); if($this->db->run_insert($sql, $this->sequenceName)) { $loadRes = true; $this->logsObj->log_by_class("Created data for '". $this->projectName ."' with version '". $insertData['version_string'] ."'", 'initialize'); @@ -1053,6 +1067,16 @@ //========================================================================= + + //========================================================================= + private function connect_logger($logCategory) { + $loggerDb = new cs_phpDB(constant('DBTYPE')); + $loggerDb->connect($this->config['DBPARAMS'], true); + $this->logsObj = new cs_webdblogger($loggerDb, $logCategory); + }//end connect_logger() + //========================================================================= + + }//end upgrade{} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-08-04 18:59:34
|
Revision: 25 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=25&view=rev Author: crazedsanity Date: 2009-08-04 18:59:26 +0000 (Tue, 04 Aug 2009) Log Message: ----------- System loads initial version information into the database for ease of use. NOTE::: this is an intermediate release. While it technically works, it has a lot of extra debugging information in it that should not be used on a production system. /cs_webdbupgrade.class.php: * MAIN::: -- requires (and extends) cs_versionAbstract -- set $gfObj as protected instead of private, for working with cs_versionAbstract. -- new private var, $allowNoDBVersion=true (for handling situations where get_database_version() would normally throw an exception). * __construct(): -- calls check_internal_upgrades() for doing running any requisite upgrades for itself. * check_internal_upgrades() [NEW]: -- performs any internal upgrades as necessary (eventually). -- NOTE::: presently, it just loads its own version into the database... future commits will finalize this logic. * check_versions(): -- if valid data was not returned from get_database_version(), then the initial version of the current project (which could also be itself) is loaded into the database. * upgrade_in_progress(): -- removed a call to get_database_version() -- if the internal databaseVersion isn't set, it throws an exception. * get_database_version(): -- if no rows were returned & there is no database error, it will throw an exception if the internal allowNoDBVersion is false; otherwise, it will return false: allows for initial loading of version info into the db. * is_higher_version(): -- calls cs_versionAbstract::is_higher_version, which is technically identical to what this used to be, save for logging. * load_table(): -- removed extra spaces from log message parts -- call load_initial_version() instead of manually inserting (so the code can be reused). * load_initial_version() [NEW]: -- inserts version and project information into the database. Modified Paths: -------------- trunk/0.1/cs_webdbupgrade.class.php Modified: trunk/0.1/cs_webdbupgrade.class.php =================================================================== --- trunk/0.1/cs_webdbupgrade.class.php 2009-08-04 16:38:31 UTC (rev 24) +++ trunk/0.1/cs_webdbupgrade.class.php 2009-08-04 18:59:26 UTC (rev 25) @@ -12,13 +12,15 @@ * */ -class cs_webdbupgrade { +require_once(constant('LIBDIR') .'/cs-versionparse/cs_version.abstract.class.php'); + +class cs_webdbupgrade extends cs_versionAbstract { /** cs_fileSystem{} object: for filesystem read/write operations. */ private $fsObj; /** cs_globalFunctions{} object: debugging, array, and string operations. */ - private $gfObj; + protected $gfObj; /** Array of configuration parameters. */ private $config = NULL; @@ -44,6 +46,9 @@ /** Name (absolute location) of *.lock file that indicates an upgrade is running. */ private $lockfile; + /** */ + private $allowNoDBVersion=true; + /** List of acceptable suffixes; example "1.0.0-BETA3" -- NOTE: these MUST be in * an order that reflects newest -> oldest; "ALPHA happens before BETA, etc. */ private $suffixList = array( @@ -143,6 +148,8 @@ $this->error_handler(__METHOD__ .": upgrade in progress: ". $this->fsObj->read($this->lockfile)); } + $this->check_internal_upgrades(); + $this->check_versions(false); }//end __construct() //========================================================================= @@ -151,6 +158,42 @@ //========================================================================= /** + * Determine if there are any upgrades that need to be performed... + */ + private function check_internal_upgrades() { + $oldVersionFileLocation = $this->versionFileLocation; + $oldUpgradeConfigFile = $this->config['UPGRADE_CONFIG_FILE']; + $this->config['UPGRADE_CONFIG_FILE'] = dirname(__FILE__) .'/upgrades/upgrade.xml'; + + //do stuff here... + $this->versionFileLocation = dirname(__FILE__) .'/VERSION'; + $this->read_version_file(); + + $this->gfObj->debug_print($this->parse_version_string($this->versionFileVersion),1); + + //if there is an error, then... uh... yeah. + try { + $this->get_database_version(); + } + catch(exception $e) { + #throw new exception(__METHOD__ .": error while retrieving database version: ". $e->getMessage()); + + //try creating the version. + $this->load_initial_version(); + } + + //reset internal vars. + $this->versionFileLocation = $oldVersionFileLocation; + $this->config['UPGRADE_CONFIG_FILE'] = $oldUpgradeConfigFile; + $this->read_version_file(); + + }//end check_internal_upgrades() + //========================================================================= + + + + //========================================================================= + /** * Where everything begins: checks if the version held in config.xml lines-up * with the one in the VERSION file; if it does, then it checks the version * listed in the database. @@ -172,6 +215,9 @@ //okay, all files present: check the version in the VERSION file. $versionFileVersion = $this->read_version_file(); $dbVersion = $this->get_database_version(); + if(!is_array($dbVersion)) { + $this->load_initial_version(); + } $versionsDiffer = TRUE; $retval = FALSE; @@ -347,10 +393,14 @@ //========================================================================= public function upgrade_in_progress($makeItSo=FALSE) { if($makeItSo === TRUE) { - $this->get_database_version(); - $details = $this->projectName .': Upgrade from '. $this->databaseVersion .' started at '. date('Y-m-d H:i:s'); - $this->create_lockfile($details); - $retval = TRUE; + if(strlen($this->databaseVersion)) { + $details = $this->projectName .': Upgrade from '. $this->databaseVersion .' started at '. date('Y-m-d H:i:s'); + $this->create_lockfile($details); + $retval = TRUE; + } + else { + $this->error_handler(__METHOD__ .": missing internal databaseVersion (". $this->databaseVersion .")"); + } } $retval = $this->check_lockfile(); @@ -488,6 +538,14 @@ "ERROR: ". $dberror .", SCHEMA LOAD ERROR::: ". $loadTableResult); } } + elseif(!strlen($dberror) && $numrows == 0) { + if($this->allowNoDBVersion) { + $retval = false; + } + else { + $this->error_handler(__METHOD__ .": no version data found for (". $this->projectName .")"); + } + } else { $this->error_handler(__METHOD__ .": failed to retrieve version... numrows=(". $numrows ."), DBERROR::: ". $dberror); } @@ -667,104 +725,13 @@ //========================================================================= - protected function is_higher_version($version, $checkIfHigher) { - $retval = FALSE; - if(!is_string($version) || !is_string($checkIfHigher)) { - $this->error_handler(__METHOD__ .": didn't get strings... ". debug_print(func_get_args(),0)); + public function is_higher_version($version, $checkIfHigher) { + try { + $retval = parent::is_higher_version($version, $checkIfHigher); } - elseif($version == $checkIfHigher) { - $retval = FALSE; + catch(exception $e) { + $this->error_handler($e->getMessage()); } - else { - $curVersionArr = $this->parse_version_string($version); - $checkVersionArr = $this->parse_version_string($checkIfHigher); - - unset($curVersionArr['version_string'], $checkVersionArr['version_string']); - - - $curVersionSuffix = $curVersionArr['version_suffix']; - $checkVersionSuffix = $checkVersionArr['version_suffix']; - - - unset($curVersionArr['version_suffix']); - - foreach($curVersionArr as $index=>$versionNumber) { - $checkThis = $checkVersionArr[$index]; - - if(is_numeric($checkThis) && is_numeric($versionNumber)) { - //set them as integers. - settype($versionNumber, 'int'); - settype($checkThis, 'int'); - - if($checkThis > $versionNumber) { - $retval = TRUE; - break; - } - elseif($checkThis == $versionNumber) { - //they're equal... - } - else { - //TODO: should there maybe be an option to throw an exception (freak out) here? - $this->logsObj->log_by_class(__METHOD__ .": while checking ". $index .", realized the new version (". $checkIfHigher .") is LOWER than current (". $version .")",'debug'); - } - } - else { - $this->error_handler(__METHOD__ .": ". $index ." is not numeric in one of the strings " . - "(versionNumber=". $versionNumber .", checkThis=". $checkThis .")"); - } - } - - //now deal with those damnable suffixes, but only if the versions are so far identical: if - // the "$checkIfHigher" is actually higher, don't bother (i.e. suffixes don't matter when - // we already know there's a major, minor, or maintenance version that's also higher. - if($retval === FALSE) { - //EXAMPLE: $version="1.0.0-BETA3", $checkIfHigher="1.1.0" - // Moving from a non-suffixed version to a suffixed version isn't supported, but the inverse is: - // i.e. (1.0.0-BETA3 to 1.0.0) is okay, but (1.0.0 to 1.0.0-BETA3) is NOT. - // Also: (1.0.0-BETA3 to 1.0.0-BETA4) is okay, but (1.0.0-BETA4 to 1.0.0-BETA3) is NOT. - if(strlen($curVersionSuffix) && strlen($checkVersionSuffix) && $curVersionSuffix == $checkVersionSuffix) { - //matching suffixes. - } - elseif(strlen($curVersionSuffix) || strlen($checkVersionSuffix)) { - //we know the suffixes are there and DO match. - if(strlen($curVersionSuffix) && strlen($checkVersionSuffix)) { - //okay, here's where we do some crazy things... - $curVersionData = $this->parse_suffix($curVersionSuffix); - $checkVersionData = $this->parse_suffix($checkVersionSuffix); - - if($curVersionData['type'] == $checkVersionData['type']) { - //got the same suffix type (like "BETA"), check the number. - if($checkVersionData['number'] > $curVersionData['number']) { - $retval = TRUE; - } - elseif($checkVersionData['number'] == $curVersionData['number']) { - $retval = FALSE; - } - else { - //umm... they're identical??? LOGIC HAS FAILED ME ALTOGETHER!!! - $retval = FALSE; - } - } - else { - //not the same suffix... see if the new one is higher. - $suffixValues = array_flip($this->suffixList); - if($suffixValues[$checkVersionData['type']] > $suffixValues[$curVersionData['type']]) { - $retval = TRUE; - } - } - - } - elseif(strlen($curVersionSuffix) && !strlen($checkVersionSuffix)) { - //i.e. "1.0.0-BETA1" to "1.0.0" --->>> OKAY! - $retval = TRUE; - } - elseif(!strlen($curVersionSuffix) && strlen($checkVersionSuffix)) { - //i.e. "1.0.0" to "1.0.0-BETA1" --->>> NOT ACCEPTABLE! - $this->logsObj->log_by_class(__METHOD__ .": from (". $version .") to (". $checkIfHigher .") isn't acceptable...?", 'debug'); - } - } - } - } return($retval); @@ -937,33 +904,20 @@ $loadTableResult = $this->db->errorMsg(); if(!strlen($loadTableResult)) { $loadTableResult = true; - $logRes = 'Successfully loaded '; + $logRes = 'Successfully loaded'; $logType = 'initialize'; //now set the initial version information... if(strlen($this->projectName) && strlen($this->versionFileVersion)) { - - //if there's an INITIAL_VERSION in the upgrade config file, use that. - $this->read_upgrade_config_file(); - if(isset($this->config['UPGRADELIST']['INITIALVERSION'])) { - $insertData = $this->parse_version_string($this->config['UPGRADELIST']['INITIALVERSION']); - } - else { - $insertData = $this->parse_version_string($this->versionFileVersion); - } - $insertData['project_name'] = $this->projectName; - - $sql = 'INSERT INTO '. $this->config['DB_TABLE'] . $this->gfObj->string_from_array($insertData, 'insert'); - if($this->db->run_insert($sql, $this->sequenceName)) { - $this->logsObj->log_by_class('Created initial version info ('. $insertData['version_string'] .')', $logType); - } - else { - $this->logsObj->log_by_class('Failed to create version info ('. $insertData['version_string'] .')', 'error'); - } + $this->load_initial_version(); } + else { + throw new exception(__METHOD__ .": missing projectName (". $this->projectName .") " . + "or versionFileVersion (". $this->versionFileVersion ."), cannot load data"); + } } else { - $logRes = 'Failed to load '; + $logRes = 'Failed to load'; $logType = 'error'; } $this->logsObj->log_by_class($logRes .' table ('. $this->config['DB_TABLE'] .') into ' . @@ -1070,6 +1024,35 @@ //========================================================================= + + //========================================================================= + public function load_initial_version() { + //if there's an INITIAL_VERSION in the upgrade config file, use that. + $this->read_upgrade_config_file(); + if(isset($this->config['UPGRADELIST']['INITIALVERSION'])) { + $insertData = $this->parse_version_string($this->config['UPGRADELIST']['INITIALVERSION']); + } + else { + $insertData = $this->parse_version_string($this->versionFileVersion); + } + $insertData['project_name'] = $this->projectName; + + $sql = 'INSERT INTO '. $this->config['DB_TABLE'] . $this->gfObj->string_from_array($insertData, 'insert'); + + $this->gfObj->debug_print(__METHOD__ .": SQL::: ". $sql,1); + if($this->db->run_insert($sql, $this->sequenceName)) { + $loadRes = true; + $this->logsObj->log_by_class("Created data for '". $this->projectName ."' with version '". $insertData['version_string'] ."'", 'initialize'); + } + else { + $this->error_handler(__METHOD__ .": failed to load initial version::: ". $e->getMessage()); + } + + return($loadRes); + }//end load_initial_version() + //========================================================================= + + }//end upgrade{} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-08-04 16:38:42
|
Revision: 24 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=24&view=rev Author: crazedsanity Date: 2009-08-04 16:38:31 +0000 (Tue, 04 Aug 2009) Log Message: ----------- Set initial version when loading table into database. /cs_webdbupgrade.class.php: * __construct(): -- use a separate connection for the logger so logs don't disappear with transactions if they get rolled-back. * read_upgrade_config_file(): -- catch exceptions from cs_fileSystem{} and wrap its own exception around it, so the error is easier to debug. * load_table(): -- call read_upgrade_config_file() to see if there is an INITIAL_VERSION to use instead of using the standard versionFileVersion (which potentially skips intermediate updates). Modified Paths: -------------- trunk/0.1/cs_webdbupgrade.class.php Modified: trunk/0.1/cs_webdbupgrade.class.php =================================================================== --- trunk/0.1/cs_webdbupgrade.class.php 2009-08-04 15:40:42 UTC (rev 23) +++ trunk/0.1/cs_webdbupgrade.class.php 2009-08-04 16:38:31 UTC (rev 24) @@ -128,7 +128,10 @@ $this->db = new cs_phpDB(constant('DBTYPE')); try { $this->db->connect($this->config['DBPARAMS']); - $this->logsObj = new cs_webdblogger($this->db, "Upgrade"); + + $loggerDb = new cs_phpDB(constant('DBTYPE')); + $loggerDb->connect($this->config['DBPARAMS'], true); + $this->logsObj = new cs_webdblogger($loggerDb, "Upgrade"); } catch(exception $e) { $this->gfObj->debug_print($this->config,1); @@ -235,7 +238,12 @@ * Read information from our config file, so we know what to expect. */ private function read_upgrade_config_file() { - $xmlString = $this->fsObj->read($this->config['UPGRADE_CONFIG_FILE']); + try { + $xmlString = $this->fsObj->read($this->config['UPGRADE_CONFIG_FILE']); + } + catch(exception $e) { + throw new exception(__METHOD__ .": failed to read upgrade config file::: ". $e->getMessage()); + } //parse the file. $xmlParser = new cs_phpxmlParser($xmlString); @@ -934,7 +942,15 @@ //now set the initial version information... if(strlen($this->projectName) && strlen($this->versionFileVersion)) { - $insertData = $this->parse_version_string($this->versionFileVersion); + + //if there's an INITIAL_VERSION in the upgrade config file, use that. + $this->read_upgrade_config_file(); + if(isset($this->config['UPGRADELIST']['INITIALVERSION'])) { + $insertData = $this->parse_version_string($this->config['UPGRADELIST']['INITIALVERSION']); + } + else { + $insertData = $this->parse_version_string($this->versionFileVersion); + } $insertData['project_name'] = $this->projectName; $sql = 'INSERT INTO '. $this->config['DB_TABLE'] . $this->gfObj->string_from_array($insertData, 'insert'); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-08-04 15:40:50
|
Revision: 23 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=23&view=rev Author: crazedsanity Date: 2009-08-04 15:40:42 +0000 (Tue, 04 Aug 2009) Log Message: ----------- Properly loads schema on first use. /cs_webdbupgrade.class.php: * MAIN::: -- new private var, $sequenceName * __construct(): -- make sure DB_TABLE and DB_PRIMARYKEY are defined configuration parameters. * get_database_version(): -- updated regex for if the table doesn't exist (this regex should be consolidated). * load_table(): -- replace the "primaryKey" var in the schema with the value from the configuration. -- pass the internal "sequenceName" to the call to run_insert(). /schema/schema.sql: * added a (configured) primary key so the id of inserts can be returned. * the "project_name" is no longer the primary key. Modified Paths: -------------- trunk/0.1/cs_webdbupgrade.class.php trunk/0.1/schema/schema.sql Modified: trunk/0.1/cs_webdbupgrade.class.php =================================================================== --- trunk/0.1/cs_webdbupgrade.class.php 2009-07-30 16:19:26 UTC (rev 22) +++ trunk/0.1/cs_webdbupgrade.class.php 2009-08-04 15:40:42 UTC (rev 23) @@ -23,6 +23,9 @@ /** Array of configuration parameters. */ private $config = NULL; + /** Name of primary key sequence of main table (for handling inserts with PostgreSQL) */ + private $sequenceName; + /** Database object. */ protected $db; @@ -103,6 +106,11 @@ $this->gfObj->debugPrintOpt = constant('DEBUGPRINTOPT'); } + if(!isset($this->config['DB_PRIMARYKEY']) || !isset($this->config['DB_TABLE'])) { + throw new exception(__METHOD__ .": no setting for DB_TABLE or DB_PRIMARYKEY, cannot continue"); + } + $this->sequenceName = $this->config['DB_TABLE'] .'_'. $this->config['DB_PRIMARYKEY'] .'_seq'; + if(!defined('DBTYPE')) { throw new exception(__METHOD__ .": required constant 'DBTYPE' not set"); } @@ -123,6 +131,7 @@ $this->logsObj = new cs_webdblogger($this->db, "Upgrade"); } catch(exception $e) { + $this->gfObj->debug_print($this->config,1); throw new exception(__METHOD__ .": failed to connect to database or logger error: ". $e->getMessage()); } @@ -458,7 +467,7 @@ if(strlen($dberror) || $numrows != 1) { // - if(preg_match('/doesn\'t exist/', $dberror)) { + if(preg_match('/doesn\'t exist/', $dberror) || preg_match('/does not exist/', $dberror)) { //add the table... $loadTableResult = $this->load_table(); if($loadTableResult === TRUE) { @@ -914,6 +923,7 @@ $schemaFileLocation = dirname(__FILE__) .'/schema/schema.sql'; $schema = file_get_contents($schemaFileLocation); $schema = str_replace('{tableName}', $this->config['DB_TABLE'], $schema); + $schema = str_replace('{primaryKey}', $this->config['DB_PRIMARYKEY'], $schema); $this->db->exec($schema); $loadTableResult = $this->db->errorMsg(); @@ -928,7 +938,7 @@ $insertData['project_name'] = $this->projectName; $sql = 'INSERT INTO '. $this->config['DB_TABLE'] . $this->gfObj->string_from_array($insertData, 'insert'); - if($this->db->run_insert($sql)) { + if($this->db->run_insert($sql, $this->sequenceName)) { $this->logsObj->log_by_class('Created initial version info ('. $insertData['version_string'] .')', $logType); } else { Modified: trunk/0.1/schema/schema.sql =================================================================== --- trunk/0.1/schema/schema.sql 2009-07-30 16:19:26 UTC (rev 22) +++ trunk/0.1/schema/schema.sql 2009-08-04 15:40:42 UTC (rev 23) @@ -14,7 +14,8 @@ -- The "{tableName}" portion will be replaced with the value of the configured -- "DB_TABLE" setting. CREATE TABLE {tableName} ( - project_name varchar(30) NOT NULL PRIMARY KEY, + {primaryKey} serial NOT NULL PRIMARY KEY, + project_name varchar(30) NOT NULL, version_string varchar(50) NOT NULL, version_major integer NOT NULL, version_minor integer NOT NULL, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-07-30 16:19:34
|
Revision: 22 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=22&view=rev Author: crazedsanity Date: 2009-07-30 16:19:26 +0000 (Thu, 30 Jul 2009) Log Message: ----------- Fix method that checks if an upgrade is in progress. /cs_webdbupgrade.class.php: * upgrade_in_progress(): -- remove default value for $retval (overwritten anyway) -- remove reference to "WORKINGONIT" -- always returns value from check_lockfile() now. -- NOTE::: previously this would report FALSE even if a lockfile was in place; this change makes the system internally consistent. Modified Paths: -------------- trunk/0.1/cs_webdbupgrade.class.php Modified: trunk/0.1/cs_webdbupgrade.class.php =================================================================== --- trunk/0.1/cs_webdbupgrade.class.php 2009-07-30 16:09:55 UTC (rev 21) +++ trunk/0.1/cs_webdbupgrade.class.php 2009-07-30 16:19:26 UTC (rev 22) @@ -329,16 +329,13 @@ //========================================================================= public function upgrade_in_progress($makeItSo=FALSE) { - $retval = FALSE; if($makeItSo === TRUE) { $this->get_database_version(); $details = $this->projectName .': Upgrade from '. $this->databaseVersion .' started at '. date('Y-m-d H:i:s'); $this->create_lockfile($details); $retval = TRUE; } - elseif(preg_match('/^upgrade/i', $this->mainConfig['WORKINGONIT'])) { - $retval = TRUE; - } + $retval = $this->check_lockfile(); return($retval); }//end upgrade_in_progress() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-07-30 16:10:07
|
Revision: 21 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=21&view=rev Author: crazedsanity Date: 2009-07-30 16:09:55 +0000 (Thu, 30 Jul 2009) Log Message: ----------- Log begin & end, fix for mixed version-only & script upgrades (#285). /cs_webdbupgrade.class.php: * perform_upgrade(): -- log the beginning of the upgrade: pulling all records of the proper category that are GREATER than the last recorded event like this will show all the information on the latest upgrade. -- pass "$toVersion" to do_single_upgrade() -- log end of the upgrade * do_single_upgrade(): -- ARG CHANGE: RENAMED ARG: #1 (now "$fromVersion") -- ARG CHANGE: NEW ARG: #2 ($toVersion=null) -- updated references from $targetVersion to $fromVersion -- use $toVersion for setting the database version: previously, it was setting the current version to be the versionFileVersion, which led directly to causing issue #285 and making backwards-compatibility a big (though undiscovered) issue. Now it correctly logs the current version in a >1 upgrade chain, and handles intermediary upgrades properly. More testing would definitely be prudent. Modified Paths: -------------- trunk/0.1/cs_webdbupgrade.class.php Modified: trunk/0.1/cs_webdbupgrade.class.php =================================================================== --- trunk/0.1/cs_webdbupgrade.class.php 2009-07-29 19:14:10 UTC (rev 20) +++ trunk/0.1/cs_webdbupgrade.class.php 2009-07-30 16:09:55 UTC (rev 21) @@ -256,6 +256,8 @@ $lockConfig = $this->upgrade_in_progress(TRUE); $this->fsObj->cd("/"); + $this->logsObj->log_by_class("Starting upgrade process...", 'begin'); + //TODO: not only should the "create_file()" method be run, but also do a sanity check by calling lock_file_exists(). if($lockConfig === 0) { //can't create the lockfile. Die. @@ -288,7 +290,7 @@ $details = __METHOD__ .": upgrading from ". $fromVersion ." to ". $toVersion ."... "; $this->logsObj->log_by_class($details, 'system'); - $this->do_single_upgrade($fromVersion); + $this->do_single_upgrade($fromVersion, $toVersion); $this->get_database_version(); $i++; @@ -317,6 +319,7 @@ $this->error_handler(__METHOD__ .": upgrade aborted:::". $e->getMessage()); $this->db->rollbackTrans(); } + $this->logsObj->log_by_class("Upgrade process complete", 'end'); } } }//end perform_upgrade() @@ -488,13 +491,13 @@ //========================================================================= - private function do_single_upgrade($targetVersion) { + private function do_single_upgrade($fromVersion, $toVersion=null) { //Use the "matching_syntax" data in the upgrade.xml file to determine the filename. - $versionIndex = "V". $this->get_full_version_string($targetVersion); + $versionIndex = "V". $this->get_full_version_string($fromVersion); if(!isset($this->config['UPGRADELIST']['MATCHING'][$versionIndex])) { //version-only upgrade. - $this->newVersion = $this->versionFileVersion; - $this->update_database_version($this->versionFileVersion); + $this->newVersion = $toVersion; + $this->update_database_version($toVersion); } else { //scripted upgrade... This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-07-29 19:14:23
|
Revision: 20 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=20&view=rev Author: crazedsanity Date: 2009-07-29 19:14:10 +0000 (Wed, 29 Jul 2009) Log Message: ----------- Fix logging of invalid version. /cs_webdbupgrade.class.php: * do_single_upgrade(): -- change the version in the log message to be the internal newVersion var (which always contains the current version: with multiple inline upgrades, it'll contain whatever version it just finished upgrading to... as opposed to the target version, final version, or nothing if the wrong one is used). Modified Paths: -------------- trunk/0.1/cs_webdbupgrade.class.php Modified: trunk/0.1/cs_webdbupgrade.class.php =================================================================== --- trunk/0.1/cs_webdbupgrade.class.php 2009-07-27 19:59:41 UTC (rev 19) +++ trunk/0.1/cs_webdbupgrade.class.php 2009-07-29 19:14:10 UTC (rev 20) @@ -517,7 +517,7 @@ $this->error_handler(__METHOD__ .": target version not specified, unable to proceed with upgrade for ". $versionIndex); } } - $this->logsObj->log_by_class("Finished upgrade to ". $upgradeData['TARGET_VERSION'], 'system'); + $this->logsObj->log_by_class("Finished upgrade to ". $this->newVersion, 'system'); }//end do_single_upgrade() //========================================================================= This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-07-27 19:59:51
|
Revision: 19 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=19&view=rev Author: crazedsanity Date: 2009-07-27 19:59:41 +0000 (Mon, 27 Jul 2009) Log Message: ----------- Fix so multiple inline upgrades work. /cs_webdbupgrade.class.php: * perform_upgrade(): -- logs total number of upgrades to be preformed -- logic for handling multiple upgrades vs. a single. * do_single_upgrade(): -- log the TARGET_VERSION instead of the matching (old) version. * get_upgrade_list(): -- use proper index of configuration so multiple inline upgrades work. Modified Paths: -------------- trunk/0.1/cs_webdbupgrade.class.php Modified: trunk/0.1/cs_webdbupgrade.class.php =================================================================== --- trunk/0.1/cs_webdbupgrade.class.php 2009-07-27 17:28:59 UTC (rev 18) +++ trunk/0.1/cs_webdbupgrade.class.php 2009-07-27 19:59:41 UTC (rev 19) @@ -281,7 +281,8 @@ try { $i=0; - $this->logsObj->log_by_class(__METHOD__ .": starting to run through the upgrade list, starting at (". $this->databaseVersion .")...", 'debug'); + $this->logsObj->log_by_class(__METHOD__ .": starting to run through the upgrade list, starting at (". $this->databaseVersion ."), " . + "total number of upgrades to perform: ". count($upgradeList), 'debug'); $this->db->beginTrans(__METHOD__); foreach($upgradeList as $fromVersion=>$toVersion) { @@ -295,12 +296,18 @@ $this->logsObj->log_by_class($details, 'system'); } - if($this->databaseVersion == $this->versionFileVersion) { - $this->logsObj->log_by_class(__METHOD__ .": finished upgrading after performing (". $i .") upgrades", 'debug'); - $this->newVersion = $this->databaseVersion; + if($i < count($upgradeList)) { + $this->logsObj->log_by_class(__METHOD__ .": completed upgrade ". $i ." of ". count($upgradeList), 'debug'); } else { - $this->error_handler(__METHOD__ .": finished upgrade, but version wasn't updated (expecting '". $this->versionFileVersion ."', got '". $this->databaseVersion ."')!!!"); + if($this->databaseVersion == $this->versionFileVersion) { + $this->logsObj->log_by_class(__METHOD__ .": finished upgrading after performing (". $i .") upgrades", 'debug'); + $this->newVersion = $this->databaseVersion; + } + else { + $this->logsObj->log_by_class(__METHOD__ .": upgradeList::: ". $this->gfObj->debug_print($upgradeList,0), 'debug'); + $this->error_handler(__METHOD__ .": finished upgrade, but version wasn't updated (expecting '". $this->versionFileVersion ."', got '". $this->databaseVersion ."')!!!"); + } } $this->remove_lockfile(); @@ -510,7 +517,7 @@ $this->error_handler(__METHOD__ .": target version not specified, unable to proceed with upgrade for ". $versionIndex); } } - $this->logsObj->log_by_class("Finished upgrade to ". $targetVersion, 'system'); + $this->logsObj->log_by_class("Finished upgrade to ". $upgradeData['TARGET_VERSION'], 'system'); }//end do_single_upgrade() //========================================================================= @@ -767,9 +774,9 @@ if(!$this->is_higher_version($dbVersion, $newVersion)) { $this->error_handler(__METHOD__ .": version (". $newVersion .") isn't higher than (". $dbVersion .")... something is broken"); } - elseif(is_array($this->config['MATCHING'])) { + elseif(is_array($this->config['UPGRADELIST']['MATCHING'])) { $lastVersion = $dbVersion; - foreach($this->config['MATCHING'] as $matchVersion=>$data) { + foreach($this->config['UPGRADELIST']['MATCHING'] as $matchVersion=>$data) { $matchVersion = preg_replace('/^V/', '', $matchVersion); if($matchVersion == $data['TARGET_VERSION']) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-07-27 17:29:06
|
Revision: 18 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=18&view=rev Author: crazedsanity Date: 2009-07-27 17:28:59 +0000 (Mon, 27 Jul 2009) Log Message: ----------- Notes about MySQL & its implicit commits. Modified Paths: -------------- trunk/0.1/README.txt Modified: trunk/0.1/README.txt =================================================================== --- trunk/0.1/README.txt 2009-07-27 17:24:28 UTC (rev 17) +++ trunk/0.1/README.txt 2009-07-27 17:28:59 UTC (rev 18) @@ -19,12 +19,13 @@ system: if the upgrade fails, everything rolls-back and it is up to a developer to figure out what went wrong--but the system is left in a CONSISTENT STATE. With MySQL, this will only work with InnoDB tables--and only if ALL AFFECTED -TABLES ARE InnoDB! On a database that doesn't use transaction-ready tables -(i.e. InnoDB tables), part of the upgrade could succeed, but another part -could fail, leaving the system in an inconsistent state... and this time, it -is up to you to fix those problems before removing the lock file that keeps -the site from working. +TABLES ARE InnoDB. There are also many things that will cause an implicit +commit, meaning the code will think its in a transaction after that point, but +it actually isn't (which is possibly worse than not having transactional +capabilities at all). +MySQL TRANSACTION INFO::: http://dev.mysql.com/doc/refman/5.0/en/implicit-commit.html + WORK FLOW: --> Is there an existing LOCK file? This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-07-27 17:24:36
|
Revision: 17 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=17&view=rev Author: crazedsanity Date: 2009-07-27 17:24:28 +0000 (Mon, 27 Jul 2009) Log Message: ----------- Added a try/catch block to try to fix MySQL problems (see issue #282) /cs_webdbupgrade.class.php: * perform_upgrade(): -- log info from check_for_version_conflict() as 'info' -- use a try/catch block: commit as normal, rollaback on excpetion. * check_for_version_conflict(): -- remove logging (avoids dupe entries). * do_single_upgrade(): -- log the final outcome as 'system' instead of the default 'error' Modified Paths: -------------- trunk/0.1/cs_webdbupgrade.class.php Modified: trunk/0.1/cs_webdbupgrade.class.php =================================================================== --- trunk/0.1/cs_webdbupgrade.class.php 2009-07-24 14:55:09 UTC (rev 16) +++ trunk/0.1/cs_webdbupgrade.class.php 2009-07-27 17:24:28 UTC (rev 17) @@ -269,35 +269,47 @@ $this->get_database_version(); //check for version conflicts. - $this->check_for_version_conflict(); + $versionConflictInfo = $this->check_for_version_conflict(); + + if($versionConflictInfo !== false) { + $this->logsObj->log_by_class("Upgrading ". $versionConflictInfo ." versions, from " . + "(". $this->databaseVersion .") to (". $this->versionFileVersion .")", 'info'); + } + $upgradeList = $this->get_upgrade_list(); - $i=0; - $this->logsObj->log_by_class(__METHOD__ .": starting to run through the upgrade list, starting at (". $this->databaseVersion .")...", 'debug'); - $this->db->beginTrans(__METHOD__); - foreach($upgradeList as $fromVersion=>$toVersion) { + try { + $i=0; + $this->logsObj->log_by_class(__METHOD__ .": starting to run through the upgrade list, starting at (". $this->databaseVersion .")...", 'debug'); + $this->db->beginTrans(__METHOD__); + foreach($upgradeList as $fromVersion=>$toVersion) { + + $details = __METHOD__ .": upgrading from ". $fromVersion ." to ". $toVersion ."... "; + $this->logsObj->log_by_class($details, 'system'); + $this->do_single_upgrade($fromVersion); + $this->get_database_version(); + $i++; + + $details = __METHOD__ .": finished upgrade #". $i .", now at version (". $this->databaseVersion .")"; + $this->logsObj->log_by_class($details, 'system'); + } - $details = __METHOD__ .": upgrading from ". $fromVersion ." to ". $toVersion ."... "; - $this->logsObj->log_by_class($details, 'system'); - $this->do_single_upgrade($fromVersion); - $this->get_database_version(); - $i++; + if($this->databaseVersion == $this->versionFileVersion) { + $this->logsObj->log_by_class(__METHOD__ .": finished upgrading after performing (". $i .") upgrades", 'debug'); + $this->newVersion = $this->databaseVersion; + } + else { + $this->error_handler(__METHOD__ .": finished upgrade, but version wasn't updated (expecting '". $this->versionFileVersion ."', got '". $this->databaseVersion ."')!!!"); + } + $this->remove_lockfile(); - $details = __METHOD__ .": finished upgrade #". $i .", now at version (". $this->databaseVersion .")"; - $this->logsObj->log_by_class($details, 'system'); + $this->db->commitTrans(); } - - if($this->databaseVersion == $this->versionFileVersion) { - $this->logsObj->log_by_class(__METHOD__ .": finished upgrading after performing (". $i .") upgrades", 'debug'); - $this->newVersion = $this->databaseVersion; + catch(exception $e) { + $this->error_handler(__METHOD__ .": upgrade aborted:::". $e->getMessage()); + $this->db->rollbackTrans(); } - else { - $this->error_handler(__METHOD__ .": finished upgrade, but version wasn't updated (expecting '". $this->versionFileVersion ."', got '". $this->databaseVersion ."')!!!"); - } - $this->remove_lockfile(); - - $this->db->commitTrans(); } } }//end perform_upgrade() @@ -420,10 +432,6 @@ } } - if($retval !== false) { - $this->logsObj->log_by_class("Upgrading ". $retval ." versions, from (". $this->databaseVersion .") to (". $this->versionFileVersion .")", 'debug'); - } - return($retval); }//end check_for_version_conflict() //========================================================================= @@ -502,7 +510,7 @@ $this->error_handler(__METHOD__ .": target version not specified, unable to proceed with upgrade for ". $versionIndex); } } - $this->logsObj->log_by_class("Finished upgrade to ". $targetVersion); + $this->logsObj->log_by_class("Finished upgrade to ". $targetVersion, 'system'); }//end do_single_upgrade() //========================================================================= This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cra...@us...> - 2009-07-24 14:55:23
|
Revision: 16 http://cs-webdbupgrade.svn.sourceforge.net/cs-webdbupgrade/?rev=16&view=rev Author: crazedsanity Date: 2009-07-24 14:55:09 +0000 (Fri, 24 Jul 2009) Log Message: ----------- Convert most exceptions to call error_handler() for logging. /cs_webdbUpgrade.class.php: * __construct(): -- only things happening AFTER database connection throw an exception. * error_handler() [NEW]: -- logs the details of the exception before throwing it. * METHODS CHANGED TO CALL error_handler(): -- read_version_file() -- read_upgrade_config_file() -- perform_upgrade() -- upgrade_in_progress() -- parse_version_string() -- check_for_version_conflict() -- get_database_version() -- do_single_upgrade() -- update_database_version() -- check_database_version() -- do_scripted_upgrade() -- is_higher_version() -- get_upgrade_list() -- parse_suffix() -- fix_xml_config() -- create_lockfile() -- remove_lockfile() -- get_full_version_string() Modified Paths: -------------- trunk/0.1/cs_webdbupgrade.class.php Modified: trunk/0.1/cs_webdbupgrade.class.php =================================================================== --- trunk/0.1/cs_webdbupgrade.class.php 2009-07-16 18:55:06 UTC (rev 15) +++ trunk/0.1/cs_webdbupgrade.class.php 2009-07-24 14:55:09 UTC (rev 16) @@ -128,7 +128,7 @@ if($this->check_lockfile()) { //there is an existing lockfile... - throw new exception(__METHOD__ .": upgrade in progress: ". $this->fsObj->read($this->lockfile)); + $this->error_handler(__METHOD__ .": upgrade in progress: ". $this->fsObj->read($this->lockfile)); } $this->check_versions(false); @@ -208,11 +208,11 @@ $this->projectName = trim($projectMatches[1][0]); } else { - throw new exception(__METHOD__ .": failed to find PROJECT name"); + $this->error_handler(__METHOD__ .": failed to find PROJECT name"); } } else { - throw new exception(__METHOD__ .": could not find VERSION data"); + $this->error_handler(__METHOD__ .": could not find VERSION data"); } return($retval); @@ -237,7 +237,7 @@ $this->config['UPGRADELIST'] = $config['UPGRADE']; } else { - throw new exception(__METHOD__ .": failed to retrieve 'UPGRADE' section; " . + $this->error_handler(__METHOD__ .": failed to retrieve 'UPGRADE' section; " . "make sure upgrade.xml's ROOT element is 'UPGRADE'"); } }//end read_upgrade_config_file() @@ -250,7 +250,7 @@ //make sure there's not already a lockfile. if($this->upgrade_in_progress()) { //ew. Can't upgrade. - throw new exception(__METHOD__ .": upgrade already in progress...????"); + $this->error_handler(__METHOD__ .": upgrade already in progress...????"); } else { $lockConfig = $this->upgrade_in_progress(TRUE); @@ -259,7 +259,7 @@ //TODO: not only should the "create_file()" method be run, but also do a sanity check by calling lock_file_exists(). if($lockConfig === 0) { //can't create the lockfile. Die. - throw new exception(__METHOD__ .": failed to set 'upgrade in progress'"); + $this->error_handler(__METHOD__ .": failed to set 'upgrade in progress'"); } else { $this->logsObj->log_by_class(__METHOD__ .": result of creating lockfile: (". $lockConfig .")", 'debug'); @@ -293,7 +293,7 @@ $this->newVersion = $this->databaseVersion; } else { - throw new exception(__METHOD__ .": finished upgrade, but version wasn't updated (expecting '". $this->versionFileVersion ."', got '". $this->databaseVersion ."')!!!"); + $this->error_handler(__METHOD__ .": finished upgrade, but version wasn't updated (expecting '". $this->versionFileVersion ."', got '". $this->databaseVersion ."')!!!"); } $this->remove_lockfile(); @@ -327,7 +327,7 @@ //========================================================================= public function parse_version_string($versionString) { if(is_null($versionString) || !strlen($versionString)) { - throw new exception(__METHOD__ .": invalid version string ($versionString)"); + $this->error_handler(__METHOD__ .": invalid version string ($versionString)"); } $suffix = ""; @@ -356,7 +356,7 @@ $retval['version_suffix'] = $suffix; } else { - throw new exception(__METHOD__ .": invalid version string format, requires MAJOR.MINOR syntax (". $versionString .")"); + $this->error_handler(__METHOD__ .": invalid version string format, requires MAJOR.MINOR syntax (". $versionString .")"); } return($retval); @@ -392,7 +392,7 @@ if($versionFileData['version_minor'] == $dbVersion['version_minor']) { if($versionFileData['version_maintenance'] == $dbVersion['version_maintenance']) { if($versionFileData['version_suffix'] == $dbVersion['version_suffix']) { - throw new exception(__METHOD__ .": no version upgrade detected, but version strings don't match (versionFile=". $versionFileData['version_string'] .", dbVersion=". $dbVersion['version_string'] .")"); + $this->error_handler(__METHOD__ .": no version upgrade detected, but version strings don't match (versionFile=". $versionFileData['version_string'] .", dbVersion=". $dbVersion['version_string'] .")"); } else { $retval = "suffix"; @@ -402,21 +402,21 @@ $retval = "maintenance"; } else { - throw new exception(__METHOD__ .": downgrading from maintenance versions is unsupported"); + $this->error_handler(__METHOD__ .": downgrading from maintenance versions is unsupported"); } } elseif($versionFileData['version_minor'] > $dbVersion['version_minor']) { $retval = "minor"; } else { - throw new exception(__METHOD__ .": downgrading minor versions is unsupported"); + $this->error_handler(__METHOD__ .": downgrading minor versions is unsupported"); } } elseif($versionFileData['version_major'] > $dbVersion['version_major']) { $retval = "major"; } else { - throw new exception(__METHOD__ .": downgrading major versions is unsupported"); + $this->error_handler(__METHOD__ .": downgrading major versions is unsupported"); } } @@ -452,12 +452,12 @@ $dberror = $this->db->errorMsg(); } else { - throw new exception(__METHOD__ .": no table in database, failed to create one... ORIGINAL " . + $this->error_handler(__METHOD__ .": no table in database, failed to create one... ORIGINAL " . "ERROR: ". $dberror .", SCHEMA LOAD ERROR::: ". $loadTableResult); } } else { - throw new exception(__METHOD__ .": failed to retrieve version... numrows=(". $numrows ."), DBERROR::: ". $dberror); + $this->error_handler(__METHOD__ .": failed to retrieve version... numrows=(". $numrows ."), DBERROR::: ". $dberror); } } else { @@ -495,11 +495,11 @@ $this->update_database_version($upgradeData['TARGET_VERSION']); } else { - throw new exception(__METHOD__ .": not enough information to run scripted upgrade for ". $versionIndex); + $this->error_handler(__METHOD__ .": not enough information to run scripted upgrade for ". $versionIndex); } } else { - throw new exception(__METHOD__ .": target version not specified, unable to proceed with upgrade for ". $versionIndex); + $this->error_handler(__METHOD__ .": target version not specified, unable to proceed with upgrade for ". $versionIndex); } } $this->logsObj->log_by_class("Finished upgrade to ". $targetVersion); @@ -532,12 +532,12 @@ $retval = $updateRes; } else { - throw new exception(__METHOD__ .": invalid result (". $updateRes .") "); + $this->error_handler(__METHOD__ .": invalid result (". $updateRes .") "); } //okay, now check that the version string matches the updated bits. if(!$this->check_database_version($this->newVersion)) { - throw new exception(__METHOD__ .": database version information is invalid: (". $this->newVersion .")"); + $this->error_handler(__METHOD__ .": database version information is invalid: (". $this->newVersion .")"); } return($retval); @@ -571,7 +571,7 @@ } else { - throw new exception(__METHOD__ .": no version string given (". $this->newVersion .")"); + $this->error_handler(__METHOD__ .": no version string given (". $this->newVersion .")"); } return($retval); @@ -613,21 +613,21 @@ $this->logsObj->log_by_class("Upgrade succeeded (". $upgradeResult .")", 'success'); } else { - throw new exception(__METHOD__ .": upgrade failed (". $upgradeResult .")"); + $this->error_handler(__METHOD__ .": upgrade failed (". $upgradeResult .")"); } $this->logsObj->log_by_class("Finished running ". $createClassName ."::". $classUpgradeMethod ."(), result was (". $upgradeResult .")", 'debug'); } else { - throw new exception(__METHOD__ .": upgrade method doesn't exist (". $createClassName ."::". $classUpgradeMethod + $this->error_handler(__METHOD__ .": upgrade method doesn't exist (". $createClassName ."::". $classUpgradeMethod ."), unable to perform upgrade "); } } else { - throw new exception(__METHOD__ .": unable to locate upgrade class name (". $createClassName .")"); + $this->error_handler(__METHOD__ .": unable to locate upgrade class name (". $createClassName .")"); } } else { - throw new exception(__METHOD__ .": upgrade filename (". $fileName .") does not exist"); + $this->error_handler(__METHOD__ .": upgrade filename (". $fileName .") does not exist"); } }//end do_scripted_upgrade() //========================================================================= @@ -638,7 +638,7 @@ protected function is_higher_version($version, $checkIfHigher) { $retval = FALSE; if(!is_string($version) || !is_string($checkIfHigher)) { - throw new exception(__METHOD__ .": didn't get strings... ". debug_print(func_get_args(),0)); + $this->error_handler(__METHOD__ .": didn't get strings... ". debug_print(func_get_args(),0)); } elseif($version == $checkIfHigher) { $retval = FALSE; @@ -677,7 +677,7 @@ } } else { - throw new exception(__METHOD__ .": ". $index ." is not numeric in one of the strings " . + $this->error_handler(__METHOD__ .": ". $index ." is not numeric in one of the strings " . "(versionNumber=". $versionNumber .", checkThis=". $checkThis .")"); } } @@ -757,7 +757,7 @@ $retval = array(); if(!$this->is_higher_version($dbVersion, $newVersion)) { - throw new exception(__METHOD__ .": version (". $newVersion .") isn't higher than (". $dbVersion .")... something is broken"); + $this->error_handler(__METHOD__ .": version (". $newVersion .") isn't higher than (". $dbVersion .")... something is broken"); } elseif(is_array($this->config['MATCHING'])) { $lastVersion = $dbVersion; @@ -765,7 +765,7 @@ $matchVersion = preg_replace('/^V/', '', $matchVersion); if($matchVersion == $data['TARGET_VERSION']) { - throw new exception(__METHOD__ .": detected invalid TARGET_VERSION in (". $matchVersion ."): make sure TARGET_VERSION is higher than matching!"); + $this->error_handler(__METHOD__ .": detected invalid TARGET_VERSION in (". $matchVersion ."): make sure TARGET_VERSION is higher than matching!"); } elseif($this->databaseVersion == $matchVersion || $this->is_higher_version($this->databaseVersion, $matchVersion)) { //the version in MATCHING is equal to or HIGHER than our database version... make sure it is NOT @@ -820,14 +820,14 @@ ); } else { - throw new exception(__METHOD__ .": invalid suffix (". $suffix .")"); + $this->error_handler(__METHOD__ .": invalid suffix (". $suffix .")"); } break; } } } else { - throw new exception(__METHOD__ .": invalid suffix (". $suffix .")"); + $this->error_handler(__METHOD__ .": invalid suffix (". $suffix .")"); } return($retval); @@ -840,7 +840,7 @@ private function fix_xml_config($config, $path=null) { $this->xmlLoops++; if($this->xmlLoops > 1000) { - throw new exception(__METHOD__ .": infinite loop detected..."); + $this->error_handler(__METHOD__ .": infinite loop detected..."); } try { @@ -848,7 +848,7 @@ } catch(exception $e) { $this->logsObj->log_by_class(__METHOD__ .': encountered exception: '. $e->getMessage()); - throw new exception($e->getMessage()); + $this->error_handler($e->getMessage()); } if(!is_array($this->tempXmlConfig)) { $this->tempXmlConfig = array(); @@ -858,7 +858,7 @@ } catch(exception $e) { $this->logsObj->log_by_class(__METHOD__ .': encountered exception: '. $e->getMessage()); - throw new exception($e->getMessage()); + $this->error_handler($e->getMessage()); } $myData = $a2p->get_data($path); @@ -875,7 +875,7 @@ $this->tempXmlConfig = $myA2p->get_data(); } else { - throw new exception(__METHOD__ .": invalid type (". $myData['type'] .")"); + $this->error_handler(__METHOD__ .": invalid type (". $myData['type'] .")"); } } else { @@ -887,7 +887,7 @@ } } else { - throw new exception(__METHOD__ .": unable to fix data on path=(". $path .")::: ". $this->gfObj->debug_print($myData,0)); + $this->error_handler(__METHOD__ .": unable to fix data on path=(". $path .")::: ". $this->gfObj->debug_print($myData,0)); } }//end fix_xml_config() //========================================================================= @@ -964,15 +964,15 @@ $this->fsObj->closeFile(); } else { - throw new exception(__METHOD__ .": failed to write contents (". $contents .") to lockfile"); + $this->error_handler(__METHOD__ .": failed to write contents (". $contents .") to lockfile"); } } else { - throw new exception(__METHOD__ .": failed to create lockfile (". $this->lockfile .")"); + $this->error_handler(__METHOD__ .": failed to create lockfile (". $this->lockfile .")"); } } else { - throw new exception(__METHOD__ .": failed to create lockfile, one already exists (". $this->lockfile .")"); + $this->error_handler(__METHOD__ .": failed to create lockfile, one already exists (". $this->lockfile .")"); } }//end create_lockfile() //========================================================================= @@ -986,11 +986,11 @@ private function remove_lockfile() { if($this->check_lockfile()) { if(!$this->fsObj->rm($this->lockfile)) { - throw new exception(__METHOD__ .": failed to remove lockfile (". $this->lockfile .")"); + $this->error_handler(__METHOD__ .": failed to remove lockfile (". $this->lockfile .")"); } } else { - throw new exception(__METHOD__ .": no lockfile (". $this->lockfile .")"); + $this->error_handler(__METHOD__ .": no lockfile (". $this->lockfile .")"); } }//end remove_lockfile() //========================================================================= @@ -1009,7 +1009,7 @@ } } else { - throw new exception(__METHOD__ .": no version string given"); + $this->error_handler(__METHOD__ .": no version string given"); } return($fullVersion); @@ -1017,6 +1017,18 @@ //========================================================================= + + //========================================================================= + public function error_handler($details) { + //log the error. + $this->logsObj->log_by_class($details, 'exception in code'); + + //now throw an exception so other code can catch it. + throw new exception($details); + }//end error_handler() + //========================================================================= + + }//end upgrade{} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |