'FileBackendDBRepoWrapper' => __DIR__ . '/includes/filerepo/FileBackendDBRepoWrapper.php',
'FileBackendError' => __DIR__ . '/includes/libs/filebackend/FileBackendError.php',
'FileBackendGroup' => __DIR__ . '/includes/filebackend/FileBackendGroup.php',
- 'FileBackendMultiWrite' => __DIR__ . '/includes/filebackend/FileBackendMultiWrite.php',
+ 'FileBackendMultiWrite' => __DIR__ . '/includes/libs/filebackend/FileBackendMultiWrite.php',
'FileBackendStore' => __DIR__ . '/includes/filebackend/FileBackendStore.php',
'FileBackendStoreOpHandle' => __DIR__ . '/includes/filebackend/FileBackendStore.php',
'FileBackendStoreShardDirIterator' => __DIR__ . '/includes/filebackend/FileBackendStore.php',
'HTMLMultiSelectField' => __DIR__ . '/includes/htmlform/fields/HTMLMultiSelectField.php',
'HTMLNestedFilterable' => __DIR__ . '/includes/htmlform/HTMLNestedFilterable.php',
'HTMLRadioField' => __DIR__ . '/includes/htmlform/fields/HTMLRadioField.php',
+ 'HTMLRestrictionsField' => __DIR__ . '/includes/htmlform/fields/HTMLRestrictionsField.php',
'HTMLSelectAndOtherField' => __DIR__ . '/includes/htmlform/fields/HTMLSelectAndOtherField.php',
'HTMLSelectField' => __DIR__ . '/includes/htmlform/fields/HTMLSelectField.php',
'HTMLSelectLimitField' => __DIR__ . '/includes/htmlform/fields/HTMLSelectLimitField.php',
'HTMLTextFieldWithButton' => __DIR__ . '/includes/htmlform/fields/HTMLTextFieldWithButton.php',
'HTMLTitleTextField' => __DIR__ . '/includes/htmlform/fields/HTMLTitleTextField.php',
'HTMLUserTextField' => __DIR__ . '/includes/htmlform/fields/HTMLUserTextField.php',
+ 'HTTPFileStreamer' => __DIR__ . '/includes/libs/filebackend/HTTPFileStreamer.php',
'HWLDFWordAccumulator' => __DIR__ . '/includes/diff/DairikiDiff.php',
'HashBagOStuff' => __DIR__ . '/includes/libs/objectcache/HashBagOStuff.php',
'HashConfig' => __DIR__ . '/includes/config/HashConfig.php',
'IEUrlExtension' => __DIR__ . '/includes/libs/IEUrlExtension.php',
'IExpiringStore' => __DIR__ . '/includes/libs/objectcache/IExpiringStore.php',
'IJobSpecification' => __DIR__ . '/includes/jobqueue/JobSpecification.php',
+ 'ILBFactory' => __DIR__ . '/includes/libs/rdbms/lbfactory/ILBFactory.php',
'ILoadBalancer' => __DIR__ . '/includes/libs/rdbms/loadbalancer/ILoadBalancer.php',
'ILoadMonitor' => __DIR__ . '/includes/libs/rdbms/loadmonitor/ILoadMonitor.php',
+ 'IMaintainableDatabase' => __DIR__ . '/includes/libs/rdbms/database/IMaintainableDatabase.php',
'IP' => __DIR__ . '/includes/libs/IP.php',
'IPSet' => __DIR__ . '/includes/compat/IPSetCompat.php',
'IPTC' => __DIR__ . '/includes/media/IPTC.php',
'RedisBagOStuff' => __DIR__ . '/includes/objectcache/RedisBagOStuff.php',
'RedisConnRef' => __DIR__ . '/includes/libs/redis/RedisConnRef.php',
'RedisConnectionPool' => __DIR__ . '/includes/libs/redis/RedisConnectionPool.php',
- 'RedisLockManager' => __DIR__ . '/includes/filebackend/lockmanager/RedisLockManager.php',
+ 'RedisLockManager' => __DIR__ . '/includes/libs/lockmanager/RedisLockManager.php',
'RedisPubSubFeedEngine' => __DIR__ . '/includes/rcfeed/RedisPubSubFeedEngine.php',
'RefreshFileHeaders' => __DIR__ . '/maintenance/refreshFileHeaders.php',
'RefreshImageMetadata' => __DIR__ . '/maintenance/refreshImageMetadata.php',
/**
* MySQL version of DBLockManager that supports shared locks.
*
- * All lock servers must have the innodb table defined in locking/filelocks.sql.
+ * Do NOT use this on connection handles that are also being used for anything
+ * else as the transaction isolation will be wrong and all the other changes will
+ * get rolled back when the locks release!
+ *
+ * All lock servers must have the innodb table defined in maintenance/locking/filelocks.sql.
* All locks are non-blocking, which avoids deadlocks.
*
* @ingroup LockManager
self::LOCK_EX => self::LOCK_EX
];
+ public function __construct( array $config ) {
+ parent::__construct( $config );
+
+ $this->session = substr( $this->session, 0, 31 ); // fit to field
+ }
+
protected function initConnection( $lockDb, IDatabase $db ) {
# Let this transaction see lock rows from other transactions
$db->query( "SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;" );
$keys[] = $key;
$data[] = [ 'fls_key' => $key, 'fls_session' => $this->session ];
if ( !isset( $this->locksHeld[$path][self::LOCK_EX] ) ) {
- $checkEXKeys[] = $key;
+ $checkEXKeys[] = $key; // this has no EX lock on $key itself
}
}
$db->insert( 'filelocks_shared', $data, __METHOD__, [ 'IGNORE' ] );
# Actually do the locking queries...
if ( $type == self::LOCK_SH ) { // reader locks
- $blocked = false;
# Bail if there are any existing writers...
if ( count( $checkEXKeys ) ) {
- $blocked = $db->selectField( 'filelocks_exclusive', '1',
+ $blocked = $db->selectField(
+ 'filelocks_exclusive',
+ '1',
[ 'fle_key' => $checkEXKeys ],
__METHOD__
);
+ } else {
+ $blocked = false;
}
# Other prospective writers that haven't yet updated filelocks_exclusive
# will recheck filelocks_shared after doing so and bail due to this entry.
# Bail if there are any existing writers...
# This may detect readers, but the safe check for them is below.
# Note: if two writers come at the same time, both bail :)
- $blocked = $db->selectField( 'filelocks_shared', '1',
+ $blocked = $db->selectField(
+ 'filelocks_shared',
+ '1',
[ 'fls_key' => $keys, "fls_session != $encSession" ],
__METHOD__
);
# Block new readers/writers...
$db->insert( 'filelocks_exclusive', $data, __METHOD__ );
# Bail if there are any existing readers...
- $blocked = $db->selectField( 'filelocks_shared', '1',
+ $blocked = $db->selectField(
+ 'filelocks_shared',
+ '1',
[ 'fls_key' => $keys, "fls_session != $encSession" ],
__METHOD__
);