===============================================================================
                    ⚠️  ARCHITECTURAL CHANGE WARNING ⚠️
===============================================================================

BREAKING CHANGES: This module has undergone significant refactoring to comply
with Drupal 10 coding standards and PHP 8.1+ compatibility.

MAJOR CHANGES:
- Property names changed: $__master → $masterConnectionId, etc.
- Method names changed: rand_weighted() → randWeighted(), etc.
- Constants updated: TRUE/FALSE/NULL → true/false/null
- Deprecated functions replaced: drupal_is_cli() → PHP_SAPI === 'cli'

MIGRATION REQUIRED: If you have custom code extending this module, you MUST
update it. See docs/BREAKING_CHANGES.md for the complete migration guide.

VERSION IMPACT: These changes require a major version bump (8.x-2.0 or 10.x-1.0)

For more information:
- docs/BREAKING_CHANGES.md - Complete migration guide
- docs/ARCHITECTURAL_UPGRADE_PLAN.md - Detailed upgrade strategy

===============================================================================

== Installation  ==

Copy the autoslave directory from the modules directory to core/lib/Drupal/Core/Database/Driver/, e.g.

%> cd [my-drupal-installation]
%> cp -r modules/autoslave/lib/Drupal/autoslave/Database/Driver/autoslave core/lib/Drupal/Core/Database/Driver/.


== Configuration ==
To reduce writes to the database it is recommended to use Memcache (or similar) for session and cache, and syslog (or similar) for logging instead of dblogging.
The following examples are based on a non-memcache setup (the lock_inc is the only memcache specific configuration).

=== Simple ===
1 master, 1 slave no failover

<?php
$databases['default']['default'] = [
  'driver' => 'autoslave',
// Optional, defaults to 'master'.
  'master' => 'master',
// Optional, defaults to 'autoslave'.
  'slave' => 'autoslave',
// Always use "master" for tables "semaphore" and "sessions".
// Optional, defaults to array('sessions', 'semaphore')
  'tables' => ['sessions', 'semaphore'],
];

$databases['default']['master'] = [
  'database' => 'mydb',
  'username' => 'username',
  'password' => 'password',
  'host' => 'master.example.com',
  'port' => '',
  'driver' => 'mysql',
  'prefix' => '',
];

$databases['default']['autoslave'] = [
  'database' => 'mydb',
  'username' => 'username',
  'password' => 'password',
  'host' => 'slave.example.com',
  'port' => '',
  'driver' => 'mysql',
  'prefix' => '',
];

// Use locking that supports force master.
$conf['lock_class'] = 'Drupal\autoslave\Lock\AutoSlaveLockBackend';
$conf['autoslave_lock_class'] = 'Drupal\Core\Lock\DatabaseLockBackend';

// Workaround for Drush (Drush doesn't support non-pdo database drivers).
// Workaround for update.php (similar problem as Drush).
if (PHP_SAPI === 'cli' || basename($_SERVER['PHP_SELF']) == 'update.php') {
  $databases['default']['default'] = $databases['default']['master'];
}

?>

=== Extreme ===
1 master pool with 2 dbs, 2 slave pools with each 2 dbs, cross failover

<?php
$databases['default']['default'] = [
  'driver' => 'autoslave',
  'master' => ['master', 'slave1', 'slave2'],
  'slave' => ['slave1', 'slave2', 'master'],
// (defaults to $conf['autoslave_assumed_replication_lag'])
  'replication lag' => 2,
// Make replication lag mitigation work cross requests for all users. Defaults to TRUE.
  'global replication lag' => TRUE,
// Path to store invalidation file for flagging unavailable connections. Defaults to empty.
  'invalidation path' => 'sites/default/files',
// Enable watchdog logging during shutdown handlers. Defaults to FALSE. Enable only if using non-db watchdog logging.
  'watchdog on shutdown' => TRUE,
// For MySQL InnoDB, make sure isolation level doesn't interfere with our intentions. Defaults to empty.
  'init_commands' => ['autoslave' => "SET SESSION tx_isolation ='READ-COMMITTED'"],
];

$databases['default']['master'][] = [
  'database' => 'mydb',
  'username' => 'username',
  'password' => 'password',
  'host' => 'master1.example.com',
  'port' => '',
  'driver' => 'mysql',
  'prefix' => '',
];

$databases['default']['master'][] = [
  'database' => 'mydb',
  'username' => 'username',
  'password' => 'password',
  'host' => 'master2.example.com',
  'port' => '',
  'driver' => 'mysql',
  'prefix' => '',
];

$databases['default']['slave1'][] = [
  'database' => 'mydb',
  'username' => 'username',
  'password' => 'password',
  'host' => 'slave1.example.com',
  'port' => '',
  'driver' => 'mysql',
  'prefix' => '',
// Defaults to FALSE, required for failover from master to slave to work.
  'readonly' => TRUE,
// Defaults to 100.
  'weight' => 70,
];

$databases['default']['slave1'][] = [
  'database' => 'mydb',
  'username' => 'username',
  'password' => 'password',
  'host' => 'slave2.example.com',
  'port' => '',
  'driver' => 'mysql',
  'prefix' => '',
  'readonly' => TRUE,
  'weight' => 30,
];

$databases['default']['slave2'][] = [
  'database' => 'mydb',
  'username' => 'username',
  'password' => 'password',
  'host' => 'slave3.example.com',
  'port' => '',
  'driver' => 'mysql',
  'prefix' => '',
  'readonly' => TRUE,
];

$databases['default']['slave2'][] = [
  'database' => 'mydb',
  'username' => 'username',
  'password' => 'password',
  'host' => 'slave4.example.com',
  'port' => '',
  'driver' => 'mysql',
  'prefix' => '',
  'readonly' => TRUE,
];

// Use locking that supports force master.
$conf['lock_class'] = 'Drupal\autoslave\Lock\AutoSlaveLockBackend';
$conf['autoslave_lock_class'] = 'Drupal\Core\Lock\DatabaseLockBackend';

// Workaround for Drush (Drush doesn't support non-pdo database drivers).
// Workaround for update.php (similar problem as Drush).
if (PHP_SAPI === 'cli' || basename($_SERVER['PHP_SELF']) == 'update.php') {
  $databases['default']['default'] = $databases['default']['master'];
}

?>

In order for failover to work for master to a slave (readonly), the AutoSlave needs to go into read-only mode. You may need to apply this bug-fix to Drupal Core, for it to work properly:

http://drupal.org/node/1889328 - Not all objects respect the query option "throw_exception"
