MediaWiki master
PoolCounterClient.php
Go to the documentation of this file.
1<?php
8
10
19 private $conn;
20
24 private $hostName;
25
29 private $manager;
30
31 public function setManager( PoolCounterConnectionManager $manager ): void {
32 $this->manager = $manager;
33 }
34
38 public function getConn() {
39 if ( !$this->conn ) {
40 $status = $this->manager->get( $this->key );
41 if ( !$status->isOK() ) {
42 return $status;
43 }
44 $this->conn = $status->value['conn'];
45 $this->hostName = $status->value['hostName'];
46
47 // Set the read timeout to be 1.5 times the pool timeout.
48 // This allows the server to time out gracefully before we give up on it.
49 stream_set_timeout( $this->conn, 0, (int)( $this->timeout * 1e6 * 1.5 ) );
50 }
51 // TODO: Convert from Status to StatusValue
52 return Status::newGood( $this->conn );
53 }
54
59 public function sendCommand( ...$args ) {
60 $args = str_replace( ' ', '%20', $args );
61 $cmd = implode( ' ', $args );
62 $status = $this->getConn();
63 if ( !$status->isOK() ) {
64 return $status;
65 }
66 $conn = $status->value;
67 $this->logger->debug( "Sending pool counter command: $cmd" );
68 if ( fwrite( $conn, "$cmd\n" ) === false ) {
69 return Status::newFatal( 'poolcounter-write-error', $this->hostName );
70 }
71 $response = fgets( $conn );
72 if ( $response === false ) {
73 return Status::newFatal( 'poolcounter-read-error', $this->hostName );
74 }
75 $response = rtrim( $response, "\r\n" );
76 $this->logger->debug( "Got pool counter response: $response" );
77 $parts = explode( ' ', $response, 2 );
78 $responseType = $parts[0];
79 switch ( $responseType ) {
80 case 'LOCKED':
81 $this->onAcquire();
82 break;
83 case 'RELEASED':
84 $this->onRelease();
85 break;
86 case 'DONE':
87 case 'NOT_LOCKED':
88 case 'QUEUE_FULL':
89 case 'TIMEOUT':
90 case 'LOCK_HELD':
91 break;
92 case 'ERROR':
93 default:
94 $parts = explode( ' ', $parts[1], 2 );
95 $errorMsg = $parts[1] ?? '(no message given)';
96 return Status::newFatal( 'poolcounter-remote-error', $errorMsg, $this->hostName );
97 }
98 return Status::newGood( constant( "PoolCounter::$responseType" ) );
99 }
100
105 public function acquireForMe( $timeout = null ) {
106 $status = $this->precheckAcquire();
107 if ( !$status->isGood() ) {
108 return $status;
109 }
110 return $this->sendCommand( 'ACQ4ME', $this->key, $this->workers, $this->maxqueue,
111 $timeout ?? $this->timeout );
112 }
113
118 public function acquireForAnyone( $timeout = null ) {
119 $status = $this->precheckAcquire();
120 if ( !$status->isGood() ) {
121 return $status;
122 }
123 return $this->sendCommand( 'ACQ4ANY', $this->key, $this->workers, $this->maxqueue,
124 $timeout ?? $this->timeout );
125 }
126
130 public function release() {
131 $status = $this->sendCommand( 'RELEASE' );
132
133 if ( $this->conn ) {
134 $this->manager->close( $this->conn );
135 $this->conn = null;
136 }
137
138 return $status;
139 }
140}
setManager(PoolCounterConnectionManager $manager)
Helper for \MediaWiki\PoolCounter\PoolCounterClient.
Semaphore semantics to restrict how many workers may concurrently perform a task.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition Status.php:44