+ protected function init( $position, $asOfTime ) {
+ $m = [];
+ if ( preg_match( '!^(.+)\.(\d+)/(\d+)$!', $position, $m ) ) {
+ $this->binLog = $m[1]; // ideally something like host name
+ $this->logPos = [ self::CORD_INDEX => (int)$m[2], self::CORD_EVENT => (int)$m[3] ];
+ $this->style = self::BINARY_LOG;
+ } else {
+ $gtids = array_filter( array_map( 'trim', explode( ',', $position ) ) );
+ foreach ( $gtids as $gtid ) {
+ $components = self::parseGTID( $gtid );
+ if ( !$components ) {
+ throw new InvalidArgumentException( "Invalid GTID '$gtid'." );
+ }
+
+ list( $domain, $pos ) = $components;
+ if ( isset( $this->gtids[$domain] ) ) {
+ // For MySQL, handle the case where some past issue caused a gap in the
+ // executed GTID set, e.g. [last_purged+1,N-1] and [N+1,N+2+K]. Ignore the
+ // gap by using the GTID with the highest ending sequence number.
+ list( , $otherPos ) = self::parseGTID( $this->gtids[$domain] );
+ if ( $pos > $otherPos ) {
+ $this->gtids[$domain] = $gtid;
+ }
+ } else {
+ $this->gtids[$domain] = $gtid;
+ }
+
+ if ( is_int( $domain ) ) {
+ $this->style = self::GTID_MARIA; // gtid_domain_id
+ } else {
+ $this->style = self::GTID_MYSQL; // server_uuid
+ }
+ }
+ if ( !$this->gtids ) {
+ throw new InvalidArgumentException( "GTID set cannot be empty." );
+ }
+ }
+
+ $this->asOfTime = $asOfTime;