Remove product literal strings in "pht()", part 18
[phabricator.git] / src / infrastructure / cluster / PhabricatorDatabaseRefParser.php
blobdb498e8a8251350edeea1628166b8bb95a84d257
1 <?php
3 final class PhabricatorDatabaseRefParser
4 extends Phobject {
6 private $defaultPort = 3306;
7 private $defaultUser;
8 private $defaultPass;
10 public function setDefaultPort($default_port) {
11 $this->defaultPort = $default_port;
12 return $this;
15 public function getDefaultPort() {
16 return $this->defaultPort;
19 public function setDefaultUser($default_user) {
20 $this->defaultUser = $default_user;
21 return $this;
24 public function getDefaultUser() {
25 return $this->defaultUser;
28 public function setDefaultPass($default_pass) {
29 $this->defaultPass = $default_pass;
30 return $this;
33 public function getDefaultPass() {
34 return $this->defaultPass;
37 public function newRefs(array $config) {
38 $default_port = $this->getDefaultPort();
39 $default_user = $this->getDefaultUser();
40 $default_pass = $this->getDefaultPass();
42 $refs = array();
44 $master_count = 0;
45 foreach ($config as $key => $server) {
46 $host = $server['host'];
47 $port = idx($server, 'port', $default_port);
48 $user = idx($server, 'user', $default_user);
49 $disabled = idx($server, 'disabled', false);
51 $pass = idx($server, 'pass');
52 if ($pass) {
53 $pass = new PhutilOpaqueEnvelope($pass);
54 } else {
55 $pass = clone $default_pass;
58 $role = $server['role'];
59 $is_master = ($role == 'master');
61 $use_persistent = (bool)idx($server, 'persistent', false);
63 $ref = id(new PhabricatorDatabaseRef())
64 ->setHost($host)
65 ->setPort($port)
66 ->setUser($user)
67 ->setPass($pass)
68 ->setDisabled($disabled)
69 ->setIsMaster($is_master)
70 ->setUsePersistentConnections($use_persistent);
72 if ($is_master) {
73 $master_count++;
76 $refs[$key] = $ref;
79 $is_partitioned = ($master_count > 1);
80 if ($is_partitioned) {
81 $default_ref = null;
82 $partition_map = array();
83 foreach ($refs as $key => $ref) {
84 if (!$ref->getIsMaster()) {
85 continue;
88 $server = $config[$key];
89 $partition = idx($server, 'partition');
90 if (!is_array($partition)) {
91 throw new Exception(
92 pht(
93 'Phabricator is configured with multiple master databases, '.
94 'but master "%s" is missing a "partition" configuration key to '.
95 'define application partitioning.',
96 $ref->getRefKey()));
99 $application_map = array();
100 foreach ($partition as $application) {
101 if ($application === 'default') {
102 if ($default_ref) {
103 throw new Exception(
104 pht(
105 'Multiple masters (databases "%s" and "%s") specify that '.
106 'they are the "default" partition. Only one master may be '.
107 'the default.',
108 $ref->getRefKey(),
109 $default_ref->getRefKey()));
110 } else {
111 $default_ref = $ref;
112 $ref->setIsDefaultPartition(true);
114 } else if (isset($partition_map[$application])) {
115 throw new Exception(
116 pht(
117 'Multiple masters (databases "%s" and "%s") specify that '.
118 'they are the partition for application "%s". Each '.
119 'application may be allocated to only one partition.',
120 $partition_map[$application]->getRefKey(),
121 $ref->getRefKey(),
122 $application));
123 } else {
124 // TODO: We should check that the application is valid, to
125 // prevent typos in application names. However, we do not
126 // currently have an efficient way to enumerate all of the valid
127 // application database names.
129 $partition_map[$application] = $ref;
130 $application_map[$application] = $application;
134 $ref->setApplicationMap($application_map);
136 } else {
137 // If we only have one master, make it the default.
138 foreach ($refs as $ref) {
139 if ($ref->getIsMaster()) {
140 $ref->setIsDefaultPartition(true);
145 $ref_map = array();
146 $master_keys = array();
147 foreach ($refs as $ref) {
148 $ref_key = $ref->getRefKey();
149 if (isset($ref_map[$ref_key])) {
150 throw new Exception(
151 pht(
152 'Multiple configured databases have the same internal '.
153 'key, "%s". You may have listed a database multiple times.',
154 $ref_key));
155 } else {
156 $ref_map[$ref_key] = $ref;
157 if ($ref->getIsMaster()) {
158 $master_keys[] = $ref_key;
163 foreach ($refs as $key => $ref) {
164 if ($ref->getIsMaster()) {
165 continue;
168 $server = $config[$key];
170 $partition = idx($server, 'partition');
171 if ($partition !== null) {
172 throw new Exception(
173 pht(
174 'Database "%s" is configured as a replica, but specifies a '.
175 '"partition". Only master databases may have a partition '.
176 'configuration. Replicas use the same configuration as the '.
177 'master they follow.',
178 $ref->getRefKey()));
181 $master_key = idx($server, 'master');
182 if ($master_key === null) {
183 if ($is_partitioned) {
184 throw new Exception(
185 pht(
186 'Database "%s" is configured as a replica, but does not '.
187 'specify which "master" it follows in configuration. Valid '.
188 'masters are: %s.',
189 $ref->getRefKey(),
190 implode(', ', $master_keys)));
191 } else if ($master_keys) {
192 $master_key = head($master_keys);
193 } else {
194 throw new Exception(
195 pht(
196 'Database "%s" is configured as a replica, but there is no '.
197 'master configured.',
198 $ref->getRefKey()));
202 if (!isset($ref_map[$master_key])) {
203 throw new Exception(
204 pht(
205 'Database "%s" is configured as a replica and specifies a '.
206 'master ("%s"), but that master is not a valid master. Valid '.
207 'masters are: %s.',
208 $ref->getRefKey(),
209 $master_key,
210 implode(', ', $master_keys)));
213 $master_ref = $ref_map[$master_key];
214 $ref->setMasterRef($ref_map[$master_key]);
215 $master_ref->addReplicaRef($ref);
218 return array_values($refs);