/**
* @param BagOStuff $store
* @param array $client Map of (ip: <IP>, agent: <user-agent> [, clientId: <hash>] )
- * @param int|null $posIndex Write counter index [optional]
+ * @param int|null $posIndex Write counter index
+ * @param string $secret Secret string for HMAC hashing [optional]
* @since 1.27
*/
- public function __construct( BagOStuff $store, array $client, $posIndex = null ) {
+ public function __construct( BagOStuff $store, array $client, $posIndex, $secret = '' ) {
$this->store = $store;
- $this->clientId = $client['clientId'] ??
- md5( $client['ip'] . "\n" . $client['agent'] );
+ if ( isset( $client['clientId'] ) ) {
+ $this->clientId = $client['clientId'];
+ } else {
+ $this->clientId = strlen( $secret )
+ ? hash_hmac( 'md5', $client['ip'] . "\n" . $client['agent'], $secret )
+ : md5( $client['ip'] . "\n" . $client['agent'] );
+ }
$this->key = $store->makeGlobalKey( __CLASS__, $this->clientId, 'v2' );
$this->waitForPosIndex = $posIndex;
* - perfLogger: PSR-3 logger instance. [optional]
* - errorLogger: Callback that takes an Exception and logs it. [optional]
* - deprecationLogger: Callback to log a deprecation warning. [optional]
+ * - secret: Secret string to use for HMAC hashing [optional]
* @throws InvalidArgumentException
*/
public function __construct( array $conf );
namespace Wikimedia\Rdbms;
use Psr\Log\LoggerInterface;
+use Psr\Log\NullLogger;
use Wikimedia\ScopedCallback;
use BagOStuff;
use EmptyBagOStuff;
private $cliMode;
/** @var string Agent name for query profiling */
private $agent;
+ /** @var string Secret string for HMAC hashing */
+ private $secret;
/** @var array[] $aliases Map of (table => (dbname, schema, prefix) map) */
private $tableAliases = [];
$this->wanCache = $conf['wanCache'] ?? WANObjectCache::newEmpty();
foreach ( self::$loggerFields as $key ) {
- $this->$key = $conf[$key] ?? new \Psr\Log\NullLogger();
+ $this->$key = $conf[$key] ?? new NullLogger();
}
$this->errorLogger = $conf['errorLogger'] ?? function ( Exception $e ) {
trigger_error( get_class( $e ) . ': ' . $e->getMessage(), E_USER_WARNING );
$this->hostname = $conf['hostname'] ?? gethostname();
$this->agent = $conf['agent'] ?? '';
$this->defaultGroup = $conf['defaultGroup'] ?? null;
+ $this->secret = $conf['secret'] ?? '';
$this->ticket = mt_rand();
}
$this->perfLogger->error( __METHOD__ . ": $fname does not have outer scope.\n" .
( new RuntimeException() )->getTraceAsString() );
- return;
+ return false;
}
// The transaction owner and any caller with the empty transaction ticket can commit
if ( $fnameEffective !== $fname ) {
$this->beginMasterChanges( $fnameEffective );
}
+
return $waitSucceeded;
}
'agent' => $this->requestInfo['UserAgent'],
'clientId' => $this->requestInfo['ChronologyClientId']
],
- $this->requestInfo['ChronologyPositionIndex']
+ $this->requestInfo['ChronologyPositionIndex'],
+ $this->secret
);
$this->chronProt->setLogger( $this->replLogger );