Merge lp://staging/~davidstrauss/pressflow/database-failover into lp://staging/pressflow

Proposed by David Strauss
Status: Rejected
Rejected by: David Strauss
Proposed branch: lp://staging/~davidstrauss/pressflow/database-failover
Merge into: lp://staging/pressflow
Diff against target: None lines
To merge this branch: bzr merge lp://staging/~davidstrauss/pressflow/database-failover
Reviewer Review Type Date Requested Status
David Strauss Pending
Review via email: mp+11606@code.staging.launchpad.net

Commit message

Built-in database failover, originally developed by David Rothstein and Acquia Hosting.

To post a comment you must log in.
50. By David Strauss

Add missing file

Unmerged revisions

50. By David Strauss

Add missing file

49. By David Strauss

Add changes from David Rothstein (Acquia Hosting).

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'includes/database.inc'
--- includes/database.inc 2009-07-01 22:36:49 +0000
+++ includes/database.inc 2009-09-11 15:02:34 +0000
@@ -130,6 +130,13 @@
130 install_goto('install.php');130 install_goto('install.php');
131 }131 }
132132
133 // If an array of possible databases (e.g., for a master-master setup) was
134 // specified and this is the first time we're trying to connect to them,
135 // choose the one we will connect to during this page request.
136 if (!isset($db_conns[$name]) && isset($db_url[$name]) && is_array($db_url[$name])) {
137 $db_conns[$name] = db_choose_active($db_url[$name], $name);
138 }
139
133 if (!isset($db_conns[$name])) {140 if (!isset($db_conns[$name])) {
134 // Initiate a new connection, using the named DB URL specified.141 // Initiate a new connection, using the named DB URL specified.
135 if (is_array($db_url)) {142 if (is_array($db_url)) {
@@ -163,9 +170,20 @@
163 _db_error_page("The database type '". $db_type ."' is unsupported. Please use either 'mysql' or 'mysqli' for MySQL, or 'pgsql' for PostgreSQL databases.");170 _db_error_page("The database type '". $db_type ."' is unsupported. Please use either 'mysql' or 'mysqli' for MySQL, or 'pgsql' for PostgreSQL databases.");
164 }171 }
165172
166 $db_conns[$name] = db_connect($connect_url);173 try {
174 $db_conns[$name] = db_connect($connect_url);
175 }
176 catch (Exception $e) {
177 _db_error_page($e->getMessage());
178 }
179
167 if (!empty($slave_connect_url)) {180 if (!empty($slave_connect_url)) {
168 $db_slave_conns[$name] = db_connect($slave_connect_url); 181 try {
182 $db_slave_conns[$name] = db_connect($slave_connect_url);
183 }
184 catch (Exception $e) {
185 _db_error_page($e->getMessage());
186 }
169 }187 }
170 }188 }
171189
@@ -184,6 +202,96 @@
184}202}
185203
186/**204/**
205 * Choose a database server to connect to during the current page request.
206 *
207 * This function will loop through a list of provided databases and attempt to
208 * connect to them in order, stopping when a successful connection is made.
209 * However, it also checks a (pluggable) cache to see if a different database
210 * server is preferred and moves that server to the front of the list so that
211 * it can be attempted before any of the others. If the database server that
212 * is eventually connected to is different from the one stored in the cache,
213 * it writes the new, preferred sever to the cache before exiting.
214 *
215 * @param $db_urls
216 * An ordered array of possible database servers to connect to. The keys
217 * should be unique identifiers for each server (e.g., "db1", "db2"), and
218 * the values should be database connection URLs. Once a database server
219 * has been chosen, the array will be replaced with a string containing the
220 * database connection URL that is actually being used.
221 * @param $name
222 * The name of the database that is being connected to. Usually this will be
223 * 'default', but alternate values can be specified if a separate, external
224 * set of database servers is being used for part of the page request (in
225 * addition to the main Drupal database).
226 * @return
227 * The new database connection.
228 */
229function db_choose_active(&$db_urls, $name) {
230 // Load the pluggable cache and check if it contains the name of a preferred
231 // database server. If so, move that server to the front of the list.
232 include_once variable_get('db_server_cache_inc', 'includes/db.server.cache.filesystem.inc');
233 if (function_exists('db_server_cache_get') && ($cached_db_server_id = db_server_cache_get($name))) {
234 if (isset($db_urls[$cached_db_server_id]) && $db_urls[$cached_db_server_id] != reset($db_urls)) {
235 $db_urls = array($cached_db_server_id => $db_urls[$cached_db_server_id]) + $db_urls;
236 }
237 }
238
239 // Loop through each database server and try to connect to it. Stop once a
240 // successful connection is made.
241 $error_message = '';
242 foreach ($db_urls as $id => $connect_url) {
243 $db_type = substr($connect_url, 0, strpos($connect_url, '://'));
244 $handler = "./includes/database.$db_type.inc";
245 if (is_file($handler)) {
246 include_once $handler;
247 // Try to connect to each server three times, with an increasing delay
248 // between each attempt.
249 $connection_attempt = 1;
250 $max_connection_attempts = 3;
251 while ($connection_attempt <= $max_connection_attempts) {
252 try {
253 // Quit the entire loop as soon as a successful connection is made.
254 $connection = db_connect($connect_url);
255 $preferred_db_server_id = $id;
256 break 2;
257 }
258 catch (Exception $e) {
259 if ($connection_attempt == $max_connection_attempts) {
260 $error_message .= ' Server '. $id .': '. $e->getMessage();
261 }
262 else {
263 // Wait 0.5 seconds before the second attempt, and 1 second before
264 // the third attempt.
265 usleep($connection_attempt * 500000);
266 }
267 }
268 $connection_attempt += 1;
269 }
270 }
271 else {
272 $error_message .= ' Server '. $id .": The database type '". $db_type ."' is unsupported. Please use either 'mysql' or 'mysqli' for MySQL, or 'pgsql' for PostgreSQL databases.";
273 }
274 }
275
276 // If no connection was made, show an error page and exit.
277 if (empty($connection)) {
278 _db_error_page($error_message);
279 }
280
281 // If the preferred database server changed, write this to the cache.
282 if (empty($cached_db_server_id) || $cached_db_server_id != $preferred_db_server_id) {
283 if (function_exists('db_server_cache_set')) {
284 db_server_cache_set($name, $preferred_db_server_id);
285 }
286 }
287
288 // Replace the list of database connection URLs with the one that is
289 // actually being used, and return the new database connection.
290 $db_urls = $db_urls[$preferred_db_server_id];
291 return $connection;
292}
293
294/**
187 * Helper function to show fatal database errors.295 * Helper function to show fatal database errors.
188 *296 *
189 * Prints a themed maintenance page with the 'Site off-line' text,297 * Prints a themed maintenance page with the 'Site off-line' text,
190298
=== modified file 'includes/database.mysql.inc'
--- includes/database.mysql.inc 2009-02-26 00:40:48 +0000
+++ includes/database.mysql.inc 2009-09-11 15:02:34 +0000
@@ -53,7 +53,10 @@
5353
54 // Check if MySQL support is present in PHP54 // Check if MySQL support is present in PHP
55 if (!function_exists('mysql_connect')) {55 if (!function_exists('mysql_connect')) {
56 throw new Exception('Unable to use the MySQL database because the MySQL extension for PHP is not installed. Check your <code>php.ini</code> to see how you can enable it.');
57 /* Original version (replaced with exception-based method above):
56 _db_error_page('Unable to use the MySQL database because the MySQL extension for PHP is not installed. Check your <code>php.ini</code> to see how you can enable it.');58 _db_error_page('Unable to use the MySQL database because the MySQL extension for PHP is not installed. Check your <code>php.ini</code> to see how you can enable it.');
59 */
57 }60 }
5861
59 // Decode url-encoded information in the db connection string62 // Decode url-encoded information in the db connection string
@@ -76,8 +79,11 @@
76 // (matched) rows, not the number of affected rows.79 // (matched) rows, not the number of affected rows.
77 $connection = @mysql_connect($url['host'], $url['user'], $url['pass'], TRUE, 2);80 $connection = @mysql_connect($url['host'], $url['user'], $url['pass'], TRUE, 2);
78 if (!$connection || !mysql_select_db(substr($url['path'], 1))) {81 if (!$connection || !mysql_select_db(substr($url['path'], 1))) {
82 throw new Exception(mysql_error());
83 /* Original version (replaced with exception-based method above):
79 // Show error screen otherwise84 // Show error screen otherwise
80 _db_error_page(mysql_error());85 _db_error_page(mysql_error());
86 */
81 }87 }
8288
83 // Force UTF-8.89 // Force UTF-8.
8490
=== modified file 'includes/database.mysqli.inc'
--- includes/database.mysqli.inc 2009-02-26 00:40:48 +0000
+++ includes/database.mysqli.inc 2009-09-11 15:02:34 +0000
@@ -57,7 +57,10 @@
57function db_connect($url) {57function db_connect($url) {
58 // Check if MySQLi support is present in PHP58 // Check if MySQLi support is present in PHP
59 if (!function_exists('mysqli_init') && !extension_loaded('mysqli')) {59 if (!function_exists('mysqli_init') && !extension_loaded('mysqli')) {
60 throw new Exception('Unable to use the MySQLi database because the MySQLi extension for PHP is not installed. Check your <code>php.ini</code> to see how you can enable it.');
61 /* Original version (replaced with exception-based method above):
60 _db_error_page('Unable to use the MySQLi database because the MySQLi extension for PHP is not installed. Check your <code>php.ini</code> to see how you can enable it.');62 _db_error_page('Unable to use the MySQLi database because the MySQLi extension for PHP is not installed. Check your <code>php.ini</code> to see how you can enable it.');
63 */
61 }64 }
6265
63 $url = parse_url($url);66 $url = parse_url($url);
@@ -76,7 +79,10 @@
76 @mysqli_real_connect($connection, $url['host'], $url['user'], $url['pass'], substr($url['path'], 1), $url['port'], NULL, MYSQLI_CLIENT_FOUND_ROWS);79 @mysqli_real_connect($connection, $url['host'], $url['user'], $url['pass'], substr($url['path'], 1), $url['port'], NULL, MYSQLI_CLIENT_FOUND_ROWS);
7780
78 if (mysqli_connect_errno() > 0) {81 if (mysqli_connect_errno() > 0) {
82 throw new Exception(mysqli_connect_error());
83 /* Original version (replaced with exception-based method above):
79 _db_error_page(mysqli_connect_error());84 _db_error_page(mysqli_connect_error());
85 */
80 }86 }
8187
82 // Force UTF-8.88 // Force UTF-8.
8389
=== modified file 'includes/database.pgsql.inc'
--- includes/database.pgsql.inc 2009-07-01 22:36:49 +0000
+++ includes/database.pgsql.inc 2009-09-11 15:02:34 +0000
@@ -47,7 +47,10 @@
47function db_connect($url) {47function db_connect($url) {
48 // Check if PostgreSQL support is present in PHP48 // Check if PostgreSQL support is present in PHP
49 if (!function_exists('pg_connect')) {49 if (!function_exists('pg_connect')) {
50 throw new Exception('Unable to use the PostgreSQL database because the PostgreSQL extension for PHP is not installed. Check your <code>php.ini</code> to see how you can enable it.');
51 /* Original version (replaced with exception-based method above):
50 _db_error_page('Unable to use the PostgreSQL database because the PostgreSQL extension for PHP is not installed. Check your <code>php.ini</code> to see how you can enable it.');52 _db_error_page('Unable to use the PostgreSQL database because the PostgreSQL extension for PHP is not installed. Check your <code>php.ini</code> to see how you can enable it.');
53 */
51 }54 }
5255
53 $url = parse_url($url);56 $url = parse_url($url);
@@ -79,7 +82,12 @@
79 $connection = @pg_connect($conn_string);82 $connection = @pg_connect($conn_string);
80 if (!$connection) {83 if (!$connection) {
81 require_once './includes/unicode.inc';84 require_once './includes/unicode.inc';
85 $error_message = decode_entities($php_errormsg);
86 ini_set('track_errors', $track_errors_previous);
87 throw new Exception($error_message);
88 /* Original version (replaced with exception-based method above):
82 _db_error_page(decode_entities($php_errormsg));89 _db_error_page(decode_entities($php_errormsg));
90 */
83 }91 }
8492
85 // Restore error tracking setting93 // Restore error tracking setting

Subscribers

People subscribed via source and target branches

to status/vote changes: