MediaWiki REL1_30
MySQLMasterPos.php
Go to the documentation of this file.
1<?php
2
3namespace Wikimedia\Rdbms;
4
5use InvalidArgumentException;
6
15class MySQLMasterPos implements DBMasterPos {
17 public $file;
19 public $pos;
21 public $gtids = [];
23 public $asOfTime = 0.0;
24
30 function __construct( $file, $pos, $gtid = '' ) {
31 $this->file = $file;
32 $this->pos = $pos;
33 $this->gtids = array_map( 'trim', explode( ',', $gtid ) );
34 $this->asOfTime = microtime( true );
35 }
36
40 function __toString() {
41 return "{$this->file}/{$this->pos}";
42 }
43
44 function asOfTime() {
45 return $this->asOfTime;
46 }
47
49 if ( !( $pos instanceof self ) ) {
50 throw new InvalidArgumentException( "Position not an instance of " . __CLASS__ );
51 }
52
53 // Prefer GTID comparisons, which work with multi-tier replication
54 $thisPosByDomain = $this->getGtidCoordinates();
55 $thatPosByDomain = $pos->getGtidCoordinates();
56 if ( $thisPosByDomain && $thatPosByDomain ) {
57 $reached = true;
58 // Check that this has positions GTE all of those in $pos for all domains in $pos
59 foreach ( $thatPosByDomain as $domain => $thatPos ) {
60 $thisPos = isset( $thisPosByDomain[$domain] ) ? $thisPosByDomain[$domain] : -1;
61 $reached = $reached && ( $thatPos <= $thisPos );
62 }
63
64 return $reached;
65 }
66
67 // Fallback to the binlog file comparisons
68 $thisBinPos = $this->getBinlogCoordinates();
69 $thatBinPos = $pos->getBinlogCoordinates();
70 if ( $thisBinPos && $thatBinPos && $thisBinPos['binlog'] === $thatBinPos['binlog'] ) {
71 return ( $thisBinPos['pos'] >= $thatBinPos['pos'] );
72 }
73
74 // Comparing totally different binlogs does not make sense
75 return false;
76 }
77
79 if ( !( $pos instanceof self ) ) {
80 throw new InvalidArgumentException( "Position not an instance of " . __CLASS__ );
81 }
82
83 // Prefer GTID comparisons, which work with multi-tier replication
84 $thisPosDomains = array_keys( $this->getGtidCoordinates() );
85 $thatPosDomains = array_keys( $pos->getGtidCoordinates() );
86 if ( $thisPosDomains && $thatPosDomains ) {
87 // Check that this has GTIDs for all domains in $pos
88 return !array_diff( $thatPosDomains, $thisPosDomains );
89 }
90
91 // Fallback to the binlog file comparisons
92 $thisBinPos = $this->getBinlogCoordinates();
93 $thatBinPos = $pos->getBinlogCoordinates();
94
95 return ( $thisBinPos && $thatBinPos && $thisBinPos['binlog'] === $thatBinPos['binlog'] );
96 }
97
104 protected function getGtidCoordinates() {
105 $gtidInfos = [];
106 foreach ( $this->gtids as $gtid ) {
107 $m = [];
108 // MariaDB style: <domain>-<server id>-<sequence number>
109 if ( preg_match( '!^(\d+)-\d+-(\d+)$!', $gtid, $m ) ) {
110 $gtidInfos[(int)$m[1]] = (int)$m[2];
111 // MySQL style: <UUID domain>:<sequence number>
112 } elseif ( preg_match( '!^(\w{8}-\w{4}-\w{4}-\w{4}-\w{12}):(\d+)$!', $gtid, $m ) ) {
113 $gtidInfos[$m[1]] = (int)$m[2];
114 } else {
115 $gtidInfos = [];
116 break; // unrecognized GTID
117 }
118
119 }
120
121 return $gtidInfos;
122 }
123
129 protected function getBinlogCoordinates() {
130 $m = [];
131 if ( preg_match( '!^(.+)\.(\d+)/(\d+)$!', (string)$this, $m ) ) {
132 return [ 'binlog' => $m[1], 'pos' => [ (int)$m[2], (int)$m[3] ] ];
133 }
134
135 return false;
136 }
137}
DBMasterPos class for MySQL/MariaDB.
float $asOfTime
UNIX timestamp.
__construct( $file, $pos, $gtid='')
int $pos
Binglog file position.
An object representing a master or replica DB position in a replicated setup.