summaryrefslogtreecommitdiff
path: root/framework/Testing/Data/Distributed/MasterSlave
diff options
context:
space:
mode:
authorgodzilla80@gmx.net <>2010-02-13 19:04:45 +0000
committergodzilla80@gmx.net <>2010-02-13 19:04:45 +0000
commit966fd66f217911d079c4bd6a87b09f4a0c5c4736 (patch)
tree26d4cda965ed5a6ddf2aeb805fcef42877584fd3 /framework/Testing/Data/Distributed/MasterSlave
parent879cced5e01d43378065c938483b55a35ff10834 (diff)
NEW: Add Beta of master/slave senario solution
- add package System.Testing.Data.Analysis - add package System.Testing.Data.Distributed - add sub package System.Testing.Data.Distributed.MasterSlave - add unittest for System.Testing.Data.Analysis
Diffstat (limited to 'framework/Testing/Data/Distributed/MasterSlave')
-rw-r--r--framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDataSourceConfig.php154
-rw-r--r--framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDbConnection.php477
-rw-r--r--framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDbTransaction.php83
3 files changed, 714 insertions, 0 deletions
diff --git a/framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDataSourceConfig.php b/framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDataSourceConfig.php
new file mode 100644
index 00000000..ee486fe8
--- /dev/null
+++ b/framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDataSourceConfig.php
@@ -0,0 +1,154 @@
+<?php
+/**
+ * TMasterSlaveDataSourceConfig class file.
+ *
+ * @author Yves Berkholz <godzilla80[at]gmx[dot]net>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005-2010 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Testing.Data.Distributed.MasterSlave
+ */
+
+ Prado::using('System.Testing.Data.Distributed.TDistributedDataSourceConfig');
+ Prado::using('System.Testing.Data.Distributed.MasterSlave.TMasterSlaveDbConnection');
+
+ /**
+ * TMasterSlaveDataSourceConfig module class provides <module> configuration for database connections in master/slave senario.
+ *
+ * IMPORTANT!!!
+ * BETA Version - Use with care and NOT in production environment (only tested with MySql)
+ *
+ * Example usage: mysql connection
+ * <code>
+ * <modules>
+ * <module id="db1" class="System.Testing.Data.Distributed.MasterSlave.TMasterSlaveDataSourceConfig"
+ * ConnectionClass="System.Testing.Data.Distributed.MasterSlave.TMasterSlaveDbConnection"
+ * DistributedConnectionClass="System.Testing.Data.Distributed.MasterSlave.TSlaveDbConnection"
+ * DbConnection.StatementAnalyserClass="System.Testing.Data.Analysis.TSimpleDbStatementAnalysis">
+ * <database ConnectionString="mysql:host=127.0.0.1;port=3306;dbname=mydatabase" Username="dbuser" Password="dbpass" />
+ * <slave ConnectionString="mysql:host=127.0.0.1;port=3307;dbname=mydatabase" Username="dbuser" Password="dbpass" Weight="3" />
+ * <slave ConnectionString="mysql:host=127.0.0.1;port=3308;dbname=mydatabase" Username="dbuser" Password="dbpass" Weight="2" />
+ * <slave ConnectionString="mysql:host=127.0.0.1;port=3309;dbname=mydatabase" Username="dbuser" Password="dbpass" Weight="5" />
+ * </module>
+ * </modules>
+ * </code>
+ *
+ * @author Yves Berkholz <godzilla80[at]gmx[dot]net>
+ * @version $Id$
+ * @package System.Testing.Data.Distributed.MasterSlave
+ * @since 4.0
+ */
+ class TMasterSlaveDataSourceConfig extends TDistributedDataSourceConfig
+ {
+ /**
+ * @var boolean
+ */
+ private $_bMasterInitialized = false;
+
+ /**
+ * @var boolean
+ */
+ private $_bSlaveInitialized = false;
+
+ /**
+ * Constructor
+ */
+ public function __construct()
+ {
+ $this->setConnectionClass('System.Testing.Data.Distributed.MasterSlave.TMasterSlaveDbConnection');
+ $this->setDistributedConnectionClass('System.Testing.Data.Distributed.MasterSlave.TSlaveDbConnection');
+ }
+
+ /**
+ * Initalize the database connection properties from attributes in slave tag.
+ * @param TXmlDocument xml configuration.
+ */
+ protected function initChildConnectionData($xml)
+ {
+ parent::initChildConnectionData($xml, 'slave');
+ }
+
+ /**
+ * @return IMasterSlaveDbConnection
+ */
+ public function getDbConnection() {
+ $id = $this->getID();
+ static $result = array();
+
+ if(!isset($result[$id]))
+ $result[$id] = parent::getDbConnection();
+
+ if(!$this->bInitialized)
+ return $result[$id];
+
+ if($this->_bMasterInitialized)
+ return $result[$id];
+
+ $this->_bMasterInitialized = true;
+
+ if(!$result[$id] instanceof IMasterSlaveDbConnection)
+ return $result[$id];
+
+ $slave = parent::getDistributedDbConnection();
+
+ if($slave instanceof ISlaveDbConnection && $slave->getMasterConnection()===null)
+ $slave->setMasterConnection($result[$id]);
+
+ if($result[$id]->getSlaveConnection()===null)
+ $result[$id]->setSlaveConnection($slave);
+
+ return $result[$id];
+ }
+
+ /**
+ * @return ISlaveDbConnection
+ */
+ public function getDistributedDbConnection() {
+ $id = $this->getID();
+ static $result = array();
+
+ if(!isset($result[$id]))
+ $result[$id] = parent::getDistributedDbConnection();
+
+ if(!$this->bInitialized)
+ return $result[$id];
+
+ if($this->_bSlaveInitialized)
+ return $result[$id];
+
+ $this->_bSlaveInitialized = true;
+
+ if(!$result[$id] instanceof ISlaveDbConnection)
+ return $result[$id];
+
+ $master = parent::getDbConnection();
+
+ if($master instanceof IMasterSlaveDbConnection && ($master->getSlaveConnection()===null))
+ $master->setSlaveConnection($result[$id]);
+
+ if($result[$id]->getMasterConnection()===null)
+ $result[$id]->setMasterConnection($master);
+
+ return $result[$id];
+ }
+
+ /**
+ * Alias for getDbConnection().
+ * @return IMasterSlaveDbConnection database connection.
+ */
+ public function getMasterDbConnection()
+ {
+ return $this->getDbConnection();
+ }
+
+ /**
+ * Alias for getDistributedDbConnection().
+ * @return ISlaveDbConnection database connection.
+ */
+ public function getSlaveDbConnection()
+ {
+ return $this->getDistributedDbConnection();
+ }
+ }
+?> \ No newline at end of file
diff --git a/framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDbConnection.php b/framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDbConnection.php
new file mode 100644
index 00000000..e6b71931
--- /dev/null
+++ b/framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDbConnection.php
@@ -0,0 +1,477 @@
+<?php
+/**
+ * IMasterSlaveDbConnection, ISlaveDbConnection inferface,
+ * TMasterSlaveDbConnection, TSlaveDbConnection class file.
+ *
+ * @author Yves Berkholz <godzilla80[at]gmx[dot]net>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005-2010 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Testing.Data.Distributed.MasterSlave
+ * @todo Test with Backport of Yii's DBO
+ */
+
+ Prado::using('System.Data.TDbConnection');
+ Prado::using('System.Testing.Data.Distributed.TDistributedDbConnection');
+ Prado::using('System.Collections.TQueue');
+ Prado::using('System.Collections.TStack');
+ Prado::using('System.Testing.Data.Distributed.MasterSlave.TMasterSlaveDbTransaction');
+
+ /**
+ * IMasterSlaveDbConnection interface
+ *
+ * @author Yves Berkholz <godzilla80[at]gmx[dot]net>
+ * @version $Id$
+ * @package System.Testing.Data.Distributed.MasterSlave
+ * @since 4.0
+ */
+ interface IMasterSlaveDbConnection extends IDistributedDbConnection
+ {
+ /**
+ * @return TQueue
+ */
+ public function getStatementQueue();
+
+ /**
+ * @return ISlaveDbConnection|null
+ */
+ public function getSlaveConnection();
+
+ /**
+ * @param ISlaveDbConnection|null
+ */
+ public function setSlaveConnection($conn);
+
+ /**
+ * @return TMasterSlaveDbConnectionForceMaster
+ */
+ public function getForceMaster();
+
+ /**
+ * @param TMasterSlaveDbConnectionForceMaster
+ */
+ public function setForceMaster($value);
+
+ }
+
+ /**
+ * ISlaveDbConnection interface
+ *
+ * @author Yves Berkholz <godzilla80[at]gmx[dot]net>
+ * @version $Id$
+ * @package System.Testing.Data.Distributed.MasterSlave
+ * @since 4.0
+ */
+ interface ISlaveDbConnection extends IDistributedDbConnection
+ {
+ /**
+ * @return IMasterSlaveDbConnection|null
+ */
+ public function getMasterConnection();
+
+ /**
+ * @param IMasterSlaveDbConnection|null
+ */
+ public function setMasterConnection($conn);
+
+ /**
+ * @return TMasterSlaveDbConnectionForceMaster
+ */
+ public function getForceMaster();
+
+ /**
+ * @param TMasterSlaveDbConnectionForceMaster
+ */
+ public function setForceMaster($value);
+ }
+
+ /**
+ * TMasterSlaveDbConnection class
+ *
+ * IMPORTANT!!!
+ * BETA Version - Use with care and NOT in production environment (only tested with MySql)
+ *
+ * TMasterSlaveDbConnection represents a master connection to a database in master/slave senario.
+ *
+ * @author Yves Berkholz <godzilla80[at]gmx[dot]net>
+ * @version $Id$
+ * @package System.Testing.Data.Distributed.MasterSlave
+ * @since 4.0
+ */
+ class TMasterSlaveDbConnection extends TDistributedDbConnection implements IMasterSlaveDbConnection
+ {
+ /**
+ * @var TSlaveDbConnection|null
+ */
+ private $_connSlave = null;
+
+ /**
+ * @var TQueue
+ */
+ private $_statementQueue = null;
+
+ /**
+ * @var integer
+ * @see TMasterSlaveDbConnectionForceMaster
+ */
+ private $_forceMaster = TMasterSlaveDbConnectionForceMaster::OFF_AUTOMATIC;
+
+ private $_forceMasterStack = null;
+
+ /**
+ * Constructor.
+ * Note, the DB connection is not established when this connection
+ * instance is created. Set {@link setActive Active} property to true
+ * to establish the connection.
+ *
+ * @param string The Data Source Name, or DSN, contains the information required to connect to the database.
+ * @param string The user name for the DSN string.
+ * @param string The password for the DSN string.
+ * @param string Charset used for DB Connection (MySql & pgsql only). If not set, will use the default charset of your database server
+ * @see http://www.php.net/manual/en/function.PDO-construct.php
+ */
+ public function __construct($dsn='', $username='', $password='', $charset='')
+ {
+ parent::__construct($dsn, $username, $password, $charset);
+ parent::setTransactionClass('System.Testing.Data.Distributed.MasterSlave.TMasterSlaveDbTransaction');
+ }
+
+ /**
+ * @return TQueue
+ */
+ public function getStatementQueue()
+ {
+ if($this->_statementQueue===null)
+ $this->_statementQueue = new TQueue();
+ return $this->_statementQueue;
+ }
+
+ /**
+ * @return ISlaveDbConnection|null
+ */
+ public function getSlaveConnection()
+ {
+ return $this->_connSlave;
+ }
+
+ /**
+ * @param ISlaveDbConnection|null
+ * @throws TDbConnectionException if the slave connection already exists
+ * @throws TDbConnectionException connection not instance of ISlaveDbConnection
+ */
+ public function setSlaveConnection($conn)
+ {
+ if($this->_connSlave !== null)
+ throw new TDbConnectionException('masterslavedbconnection_connection_exists', get_class($this), 'SlaveConnection');
+
+ if($conn!==null && !$conn instanceof ISlaveDbConnection)
+ throw new TDbConnectionException('masterslavedbconnection_interface_required', get_class($this), 'SlaveConnection', 'ISlaveDbConnection');
+
+ $this->_connSlave = $conn;
+
+ if($this->_connSlave===null) return;
+ if($this->_connSlave->getMasterConnection()!==null) return;
+
+ $this->_connSlave->setMasterConnection($this);
+ }
+
+ /**
+ * Creates a command for execution.
+ * @param string SQL statement associated with the new command.
+ * @return TDistributedDbCommand the DB command
+ * @throws TDbException if the connection is not active
+ */
+ public function createCommand($sql)
+ {
+ $force = $this->getForceMaster();
+ if($force == TMasterSlaveDbConnectionForceMaster::ON_MANUAL || $force == TMasterSlaveDbConnectionForceMaster::ON_TRANSACTION)
+ {
+ Prado::log('ForceMaster: ' . $force, TLogger::DEBUG, 'System.Testing.Data.Distributed.MasterSlave.TMasterSlaveDbConnection');
+ return new TDistributedDbCommand($this, $sql, TDbStatementClassification::UNKNOWN);
+ }
+
+ $bEnqueue = false;
+ $bMaster = true;
+
+ $classification = $this->getStatementClassification($sql);
+
+ switch($classification) {
+ case TDbStatementClassification::CONTEXT:
+ $bEnqueue = true;
+ $bMaster = true;
+ break;
+ case TDbStatementClassification::SQL:
+ $bMaster = false;
+ break;
+ case TDbStatementClassification::TCL:
+ $this->setForceMaster(TMasterSlaveDbConnectionForceMaster::ON_TCL);
+ case TDbStatementClassification::DDL:
+ case TDbStatementClassification::DML:
+ case TDbStatementClassification::DCL:
+ case TDbStatementClassification::UNKNOWN:
+ default:
+ $bMaster = true;
+ break;
+ }
+
+ $bMaster = $bMaster || $this->getForceMaster();
+
+ $result = new TDistributedDbCommand(($bMaster ? $this : $this->getSlaveConnection()), $sql, $classification);
+ //$result = new TDistributedDbCommand($this, $sql, $classification);
+
+ if($bEnqueue)
+ $this->getStatementQueue()->enqueue($result);
+
+ return $result;
+ }
+
+ /**
+ * @return TMasterSlaveDbConnectionForceMaster
+ */
+ public function getForceMaster()
+ {
+ return $this->_forceMaster;
+ }
+
+ /**
+ * @param TMasterSlaveDbConnectionForceMaster
+ */
+ public function setForceMaster($value)
+ {
+ if($this->_forceMasterStack===null)
+ $this->_forceMasterStack = new TStack();
+
+ if($value)
+ {
+ $this->_forceMaster = (integer)$value;
+ $this->_forceMasterStack->push((integer)$value);
+ }
+ elseif($this->_forceMasterStack->count() > 0)
+ $this->_forceMaster = $this->_forceMasterStack->pop();
+ else
+ $this->_forceMaster = (integer)$value;
+ }
+
+ /**
+ * @return TDbConnectionServerRole
+ */
+ public function getServerRole()
+ {
+ return TDbConnectionServerRole::Master;
+ }
+ }
+
+ /**
+ * TSlaveDbConnection class
+ *
+ * IMPORTANT!!!
+ * BETA Version - Use with care and NOT in production environment (only tested with MySql)
+ *
+ * TSlaveDbConnection represents a readonly connection to a database in master/slave senario.
+ *
+ * @author Yves Berkholz <godzilla80[at]gmx[dot]net>
+ * @version $Id$
+ * @package System.Testing.Data.Distributed.MasterSlave
+ * @since 4.0
+ */
+ class TSlaveDbConnection extends TDbConnection implements ISlaveDbConnection
+ {
+ /**
+ * @var TMasterSlaveDbConnection|null
+ */
+ private $_connMaster = null;
+
+ /**
+ * @return IMasterSlaveDbConnection|null
+ */
+ public function getMasterConnection()
+ {
+ return $this->_connMaster;
+ }
+
+ /**
+ * @param IMasterSlaveDbConnection|null
+ * @throws TDbConnectionException if the master connection already exists
+ * @throws TDbConnectionException connection not instance of IMasterSlaveDbConnection
+ */
+ public function setMasterConnection($conn)
+ {
+ if($this->_connMaster!==null)
+ throw new TDbConnectionException('masterslavedbconnection_connection_exists', get_class($this), 'MasterConnection');
+
+ if($conn!==null && !$conn instanceof IMasterSlaveDbConnection)
+ throw new TDbConnectionException('masterslavedbconnection_interface_required', get_class($this), 'MasterConnection', 'IMasterSlaveDbConnection');
+
+ $this->_connMaster = $conn;
+ }
+
+ /**
+ * Creates a command for execution.
+ * @param string SQL statement associated with the new command.
+ * @return TDistributedDbCommand the DB command
+ * @throws TDbException if the connection is not active
+ */
+ public function createCommand($sql)
+ {
+ $force = $this->getForceMaster();
+ if($force == TMasterSlaveDbConnectionForceMaster::ON_MANUAL || $force == TMasterSlaveDbConnectionForceMaster::ON_TRANSACTION)
+ {
+ Prado::log('ForceMaster: ' . $force, TLogger::DEBUG, 'System.Testing.Data.Distributed.MasterSlave.TSlaveDbConnection');
+ return new TDistributedDbCommand($this->getMasterConnection(), $sql, TDbStatementClassification::UNKNOWN);
+ }
+
+ $bEnqueue = false;
+ $bMaster = false;
+
+ $classification = $this->getStatementClassification($sql);
+
+ switch($classification) {
+ case TDbStatementClassification::SQL:
+ $bMaster = false;
+ break;
+ case TDbStatementClassification::CONTEXT:
+ $bEnqueue = true;
+ $bMaster = true;
+ break;
+ case TDbStatementClassification::TCL:
+ $this->setForceMaster(TMasterSlaveDbConnectionForceMaster::ON_TCL);
+ case TDbStatementClassification::DDL:
+ case TDbStatementClassification::DML:
+ case TDbStatementClassification::DCL:
+ case TDbStatementClassification::UNKNOWN:
+ default:
+ $bMaster = true;
+ break;
+ }
+
+ $bMaster = $bMaster || $this->getForceMaster();
+
+ $result = new TDistributedDbCommand(($bMaster ? $this->getMasterConnection() : $this), $sql, $classification);
+
+ if($bEnqueue)
+ $this->getMasterConnection()->getStatementQueue()->enqueue($result);
+
+ return $result;
+ }
+
+ /**
+ * Starts a transaction.
+ * @return TDbTransaction the transaction initiated
+ * @throws TDbException if no master connection exists or the connection is not active
+ */
+ public function beginTransaction()
+ {
+ if($this->getMasterConnection() === null)
+ throw new TDbException('slavedbconnection_requires_master', getclass($this), 'MasterConnection');
+
+ return $this->getMasterConnection()->beginTransaction();
+ }
+
+ /**
+ * @return string Transaction class name to be created by calling {@link TDbConnection::beginTransaction}.
+ * @throws TDbException if no master connection exists
+ */
+ public function getTransactionClass()
+ {
+ if($this->getMasterConnection() === null)
+ throw new TDbException('slavedbconnection_requires_master', getclass($this), 'MasterConnection');
+ return $this->getMasterConnection()->getTransactionClass();
+ }
+
+ /**
+ * @param string Transaction class name to be created by calling {@link TDbConnection::beginTransaction}.
+ * @throws TDbException if no master connection exists
+ */
+ public function setTransactionClass($value)
+ {
+ if($this->getMasterConnection() === null)
+ throw new TDbException('slavedbconnection_requires_master', getclass($this), 'MasterConnection');
+ $this->getMasterConnection()->setTransactionClass($value);
+ }
+
+ /**
+ * Gets the statement analyser of type given by
+ * {@link setStatementAnalyserClass StatementAnalyserClass }.
+ * @return IDbStatementAnalysis statement analyser.
+ * @throws TDbException if no master connection exists
+ */
+ public function getStatementAnalyser()
+ {
+ if($this->getMasterConnection() === null)
+ throw new TDbException('slavedbconnection_requires_master', getclass($this), 'MasterConnection');
+ return $this->getMasterConnection()->getStatementAnalyser();
+ }
+
+ /**
+ * The statement analyser class name to be created when {@link getStatementAnalyserClass}
+ * method is called. The {@link setStatementAnalyserClass StatementAnalyserClass}
+ * property must be set before calling {@link getStatementAnalyser} if you wish to
+ * create the connection using the given class name.
+ * @param string Statement analyser class name.
+ * @throws TDbException if no master connection exists
+ */
+ public function setStatementAnalyserClass($value)
+ {
+ if($this->getMasterConnection() === null)
+ throw new TDbException('slavedbconnection_requires_master', getclass($this), 'MasterConnection');
+ $this->getMasterConnection()->setStatementAnalyserClass($value);
+ }
+
+ /**
+ * @param string Statement analyser class name to be created.
+ * @throws TDbException if no master connection exists
+ */
+ public function getStatementAnalyserClass()
+ {
+ if($this->getMasterConnection() === null)
+ throw new TDbException('slavedbconnection_requires_master', getclass($this), 'MasterConnection');
+ return $this->getMasterConnection()->getStatementAnalyserClass();
+ }
+
+ /**
+ * @return TMasterSlaveDbConnectionForceMaster
+ * @throws TDbException if no master connection exists
+ */
+ public function getForceMaster()
+ {
+ if($this->getMasterConnection() === null)
+ throw new TDbException('slavedbconnection_requires_master', getclass($this), 'MasterConnection');
+ return $this->getMasterConnection()->getForceMaster();
+ }
+
+ /**
+ * @param TMasterSlaveDbConnectionForceMaster
+ * @throws TDbException if no master connection exists
+ */
+ public function setForceMaster($value)
+ {
+ if($this->getMasterConnection() === null)
+ throw new TDbException('slavedbconnection_requires_master', getclass($this), 'MasterConnection');
+ $this->getMasterConnection()->setForceMaster($value);
+ }
+
+ /**
+ * @return TDbConnectionServerRole
+ */
+ public function getServerRole()
+ {
+ return TDbConnectionServerRole::Slave;
+ }
+ }
+
+ /**
+ * TMasterSlaveDbConnectionForceMaster class
+ *
+ * @author Yves Berkholz <godzilla80[at]gmx[dot]net>
+ * @version $Id$
+ * @package System.Testing.Data.Distributed.MasterSlave
+ * @since 4.0
+ */
+ class TMasterSlaveDbConnectionForceMaster extends TEnumerable
+ {
+ const OFF_AUTOMATIC = 0;
+ const ON_MANUAL = 1;
+ const ON_TCL = -1;
+ const ON_TRANSACTION = -2;
+ }
diff --git a/framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDbTransaction.php b/framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDbTransaction.php
new file mode 100644
index 00000000..254afdb5
--- /dev/null
+++ b/framework/Testing/Data/Distributed/MasterSlave/TMasterSlaveDbTransaction.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * TMasterSlaveDbTransaction class file.
+ *
+ * @author Yves Berkholz <godzilla80[at]gmx[dot]net>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005-2010 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Testing.Data.Distributed.MasterSlave
+ */
+ Prado::using('System.Data.TDbTransaction');
+
+ /**
+ * TMasterSlaveDbTransaction class
+ *
+ * IMPORTANT!!!
+ * BETA Version - Use with care and NOT in production environment (only tested with MySql)
+ *
+ * TMasterSlaveDbTransaction represents a DB transaction in master/slave senario.
+ *
+ * @author Yves Berkholz <godzilla80[at]gmx[dot]net>
+ * @version $Id$
+ * @package System.Testing.Data.Distributed.MasterSlave
+ * @since 4.0
+ */
+ class TMasterSlaveDbTransaction extends TDbTransaction
+ {
+ /**
+ * @var boolean
+ */
+ private $_compatible = false;
+
+ /**
+ * Constructor.
+ * @param TDbConnection the connection associated with this transaction
+ * @see TDbConnection::beginTransaction
+ */
+ public function __construct(TDbConnection $connection)
+ {
+ if($connection instanceof ISlaveDbConnection)
+ {
+ $this->_compatible = true;
+ $master = $connection->getMasterConnection();
+ $master->setForceMaster(TMasterSlaveDbConnectionForceMaster::ON_TRANSACTION);
+ Prado::log('contstuct, ForceMaster: ON_TRANSACTION', TLogger::DEBUG, 'System.Testing.Data.Distributed.MasterSlave.TMasterSlaveDbTransaction');
+ parent::__construct($master);
+ }
+ else
+ {
+ if($connection instanceof IMasterSlaveDbConnection)
+ {
+ $this->_compatible = true;
+ $connection->setForceMaster(TMasterSlaveDbConnectionForceMaster::ON_TRANSACTION);
+ Prado::log('contstuct, ForceMaster: ON_TRANSACTION', TLogger::DEBUG, 'System.TestingData.Distributed.MasterSlave.TMasterSlaveDbTransaction');
+ }
+ parent::__construct($connection);
+ }
+ }
+
+ /**
+ * Commits a transaction.
+ * @throws TDbException if the transaction or the DB connection is not active.
+ */
+ public function commit()
+ {
+ if($this->_compatible) $this->getConnection()->setForceMaster(TMasterSlaveDbConnectionForceMaster::OFF_AUTOMATIC);
+ Prado::log('commit, ForceMaster: OFF_AUTOMATIC', TLogger::DEBUG, 'System.Testing.Data.Distributed.MasterSlave.TMasterSlaveDbTransaction');
+ parent::commit();
+ }
+
+ /**
+ * Rolls back a transaction.
+ * @throws TDbException if the transaction or the DB connection is not active.
+ */
+ public function rollback()
+ {
+ if($this->_compatible) $this->getConnection()->setForceMaster(TMasterSlaveDbConnectionForceMaster::OFF_AUTOMATIC);
+ Prado::log('rollback, ForceMaster: OFF_AUTOMATIC', TLogger::DEBUG, 'System.Testing.Data.Distributed.MasterSlave.TMasterSlaveDbTransaction');
+ parent::rollback();
+ }
+ }
+?> \ No newline at end of file