source: trunk/www/model/realm.php@ 68

Last change on this file since 68 was 67, checked in by george, 16 years ago
  • Opraveno: Zpracování informací o selhání serveru a uložení do datanáze.
  • Opraveno: Generování čísla světů do databáze realmlistu a konfiguračních souborů realmů.
File size: 15.5 KB
Line 
1<?php
2
3class Realm extends Module
4{
5 var $Id;
6 var $Data;
7 var $Task;
8
9 function __construct($Database, $Id)
10 {
11 $this->Database = $Database;
12 $this->Task = new Task($Database);
13 $this->Id = $Id;
14 $DbResult = $this->Database->query('SELECT * FROM `Realm` WHERE `Id`='.$Id);
15 if($DbResult->num_rows > 0)
16 {
17 $this->Data = $DbResult->fetch_assoc();
18 $DbResult = $this->Database->query('SELECT * FROM `Database` WHERE `Id`='.$this->Data['Database']);
19 if($DbResult->num_rows > 0) $this->Data['Database'] = $DbResult->fetch_assoc();
20 else $this->Data['Database'] = array('Emulator' => 0);
21 $DbResult = $this->Database->query('SELECT * FROM `Emulator` WHERE `Id`='.$this->Data['Database']['Emulator']);
22 if($DbResult->num_rows > 0) $this->Data['Database']['Emulator'] = $DbResult->fetch_assoc();
23 else $this->Data['Database']['Emulator'] = array('Client' => 0);
24 $DbResult = $this->Database->query('SELECT * FROM `Client` WHERE `Id`='.$this->Data['Database']['Emulator']['Client']);
25 if($DbResult->num_rows > 0) $this->Data['Database']['Emulator']['Client'] = $DbResult->fetch_assoc();
26 else $this->Data['Database']['Emulator']['Client'] = array();
27 }
28 }
29
30 function GetState()
31 {
32 global $System;
33
34 $State = array();
35 $State['WorlddPortState'] = $System->NetworkPortState('localhost', $this->Data['NetworkPortWorldd']);
36 $State['Online'] = $State['WorlddPortState'];
37 $DbResult = $this->Database->query('SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = "realm'.$this->Id.'_characters"');
38 $DbRow = $DbResult->fetch_row();
39 if($DbRow[0] > 0)
40 {
41 $DbResult = $this->Database->query('SELECT COUNT(*) FROM realm'.$this->Id.'_characters.characters AS T WHERE T.online = 1');
42 $DbRow = $DbResult->fetch_row();
43 $State['CharacterOnlineCount'] = $DbRow[0];
44 $DbResult = $this->Database->query('SELECT COUNT(*) FROM realm'.$this->Id.'_characters.characters AS T');
45 $DbRow = $DbResult->fetch_row();
46 $State['CharacterCount'] = $DbRow[0];
47 } else
48 {
49 $State['CharacterOnlineCount'] = 0;
50 $State['CharacterCount'] = 0;
51 }
52 return($State);
53 }
54
55 function CreateDatabase()
56 {
57 $this->Database->query('CREATE DATABASE `realm'.$this->Id.'_mangos`');
58 $this->Database->query('CREATE DATABASE `realm'.$this->Id.'_characters`');
59 $this->Database->query('CREATE DATABASE `realm'.$this->Id.'_scriptdev2`');
60 $this->Database->query('GRANT ALL PRIVILEGES ON `realm'.$this->Id.'\_mangos` . * TO "server'.$this->Data['Server'].'"@"localhost" WITH GRANT OPTION');
61 $this->Database->query('GRANT ALL PRIVILEGES ON `realm'.$this->Id.'\_characters` . * TO "server'.$this->Data['Server'].'"@"localhost" WITH GRANT OPTION');
62 $this->Database->query('GRANT ALL PRIVILEGES ON `realm'.$this->Id.'\_scriptdev2` . * TO "server'.$this->Data['Server'].'"@"localhost" WITH GRANT OPTION');
63 }
64
65 function DeleteDatabase()
66 {
67 $this->Database->query('DROP DATABASE `realm'.$this->Id.'_mangos`');
68 $this->Database->query('DROP DATABASE `realm'.$this->Id.'_characters`');
69 $this->Database->query('DROP DATABASE `realm'.$this->Id.'_scriptdev2`');
70 }
71
72 function ImportDatabase($Delete = false)
73 {
74 $this->Lock();
75 $CommandList = array(
76 'php www/shell.php RealmLock '.$this->Id,
77 );
78
79 // Empty all tables
80 if($Delete == true)
81 {
82 $CommandList = array_merge($CommandList, array(
83 'mysql --silent --skip-column-names -u server'.$this->Data['Server'].' -pserver'.$this->Data['Server'].' realm'.$this->Id.'_mangos -e "show tables" | gawk \'{print "drop table " $1 ";"}\' | mysql -u server'.$this->Data['Server'].' -pserver'.$this->Data['Server'].' realm'.$this->Id.'_mangos',
84 'mysql --silent --skip-column-names -u server'.$this->Data['Server'].' -pserver'.$this->Data['Server'].' realm'.$this->Id.'_characters -e "show tables" | gawk \'{print "drop table " $1 ";"}\' | mysql -u server'.$this->Data['Server'].' -pserver'.$this->Data['Server'].' realm'.$this->Id.'_characters',
85 'mysql --silent --skip-column-names -u server'.$this->Data['Server'].' -pserver'.$this->Data['Server'].' realm'.$this->Id.'_scriptdev2 -e "show tables" | gawk \'{print "drop table " $1 ";"}\' | mysql -u server'.$this->Data['Server'].' -pserver'.$this->Data['Server'].' realm'.$this->Id.'_scriptdev2',
86 ));
87 }
88
89 // Lookup nearest database with full import
90 $DbResult = $this->Database->query('SELECT * FROM `Database` WHERE (`Emulator` <> 0) AND (`Revision` <= '.$this->Data['Database']['Revision'].') AND (`SourceFileName` <> "") ORDER BY `Revision` DESC');
91 $Database = $DbResult->fetch_assoc();
92
93 $CommandList = array_merge($CommandList, array(
94 'mysql --user=server'.$this->Data['Server'].' --password=server'.$this->Data['Server'].' realm'.$this->Id.'_mangos < database/'.$Database['Id'].'/'.$Database['SourceFileName'],
95 'mysql --user=server'.$this->Data['Server'].' --password=server'.$this->Data['Server'].' realm'.$this->Id.'_scriptdev2 < emulator/'.$Database['Emulator'].'/source/src/bindings/ScriptDev2/sql/scriptdev2_create_structure.sql',
96 'mysql --user=server'.$this->Data['Server'].' --password=server'.$this->Data['Server'].' realm'.$this->Id.'_scriptdev2 < emulator/'.$Database['Emulator'].'/source/src/bindings/ScriptDev2/sql/scriptdev2_script_full.sql',
97 'mysql --user=server'.$this->Data['Server'].' --password=server'.$this->Data['Server'].' realm'.$this->Id.'_mangos < emulator/'.$Database['Emulator'].'/source/src/bindings/ScriptDev2/sql/mangos_scriptname_full.sql',
98 'mysql --user=server'.$this->Data['Server'].' --password=server'.$this->Data['Server'].' realm'.$this->Id.'_characters < emulator/'.$Database['Emulator'].'/source/sql/characters.sql'));
99 if($Database['ACIDSourceFileName'] != '')
100 $CommandList[] = 'mysql --user=server'.$this->Data['Server'].' --password=server'.$this->Data['Server'].' realm'.$this->Id.'_mangos < database/'.$Database['Id'].'/'.$Database['ACIDSourceFileName'];
101 $CommandList[] = 'php www/shell.php RealmDatabaseChange '.$this->Id.' '.$Database['Id'];
102 $commandList[] = 'php www/shell.php RealmUnLock '.$this->Id;
103 $this->Task->Add('Inicializace databáze', $CommandList);
104
105 if($Database['Id'] != $this->Data['Database']['Id'])
106 {
107 $NewDatabaseId = $this->Data['Database']['Id'];
108 $this->Data['Database']['Id'] = $Database['Id'];
109 $this->Update($NewDatabaseId, false, false);
110 }
111 return('Úloha načtení nové databáze zařazena do fronty.');
112 }
113
114 function Start()
115 {
116 $this->Lock();
117 $this->SaveConfiguration();
118 $this->Task->Add('Start světa', array(
119 'php www/shell.php RealmLock '.$this->Id,
120 'realm/'.$this->Id.'/bin/start.sh',
121 'php www/shell.php RealmUnLock '.$this->Id,
122 ));
123 return('Požadavek na start světa zařazen.');
124 }
125
126 function Stop()
127 {
128 $this->Lock();
129 $this->Task->Add('Zastavení světa', array(
130 'php www/shell.php RealmLock '.$this->Id,
131 'realm/'.$this->Id.'/bin/stop.sh',
132 'php www/shell.php RealmUnLock '.$this->Id,
133 ));
134 return('Požadavek na zastavení světa zařazen.');
135 }
136
137 function UpdateRealmlist()
138 {
139 $Server = new Server($this->Database, $this->Data['Server']);
140 $Server->UpdateRealmList();
141 }
142
143 function SaveConfiguration()
144 {
145 $this->SetupConfigurationFiles();
146 $this->UpdateRealmlist();
147 $this->UpdateScripts();
148 }
149
150 function UpdateScripts()
151 {
152 global $Config;
153
154 $RealmBinDir = '../realm/'.$this->Id.'/bin/';
155 if(!file_exists($RealmBinDir)) mkdir($RealmBinDir, 0777, true);
156
157 // GDB script
158 $ScriptFileName = '../realm/'.$this->Id.'/bin/mangos.gdb';
159 $Content = array
160 (
161 'run -c realm/'.$this->Id.'/etc/mangosd.conf',
162 'info thread',
163 );
164 for($I = 1; $I < $Config['MangosWorlddThreadCountMax']; $I++)
165 $Content[] = 'thread apply '.$I.' bt full';
166 file_put_contents($ScriptFileName, implode("\n", $Content));
167 chmod($ScriptFileName, 0666);
168
169 // Start script
170 $ScriptFileName = '../realm/'.$this->Id.'/bin/start.sh';
171 $Content = array
172 (
173 '#!/bin/sh',
174 'if [ -z `ps -ef | grep \'SCREEN -A -m -d -S realm'.$this->Id.'-worldd\' | grep -v grep | awk \'{print $2}\'` ]',
175 'then',
176 'screen -A -m -d -S realm'.$this->Id.'-worldd realm/'.$this->Id.'/bin/worldd_restarter.sh',
177 'fi',
178 );
179 file_put_contents($ScriptFileName, implode("\n", $Content));
180 chmod($ScriptFileName, 0777);
181
182 $ScriptFileName = '../realm/'.$this->Id.'/bin/worldd_restarter.sh';
183 $Content = array
184 (
185 '#!/bin/sh',
186 'while [ 1=1 ] ; do',
187 'gdb emulator/'.$this->Data['Database']['Emulator']['Id'].'/bin/mangos-worldd -x realm/'.$this->Id.'/bin/mangos.gdb --batch >>realm/'.$this->Id.'/log/mangos-worldd.log 2>>realm/'.$this->Id.'/log/mangos-worldd.err',
188 'php www/shell.php ServerProcessLog '.$this->Id.' >>realm/'.$this->Id.'/log/mangos_debug.log 2>>realm/'.$this->Id.'/log/mangos_debug.err',
189 'sleep 3',
190 'done',
191 );
192 file_put_contents($ScriptFileName, implode("\n", $Content));
193 chmod($ScriptFileName, 0777);
194
195 // Stop script
196 $ScriptFileName = '../realm/'.$this->Id.'/bin/stop.sh';
197 $Content = array
198 (
199 '#!/bin/sh',
200 'ps -ef | grep \'SCREEN -A -m -d -S realm'.$this->Id.'-worldd\' | grep -v grep | awk \'{print $2}\' | xargs -i kill {}',
201 );
202 file_put_contents($ScriptFileName, implode("\n", $Content));
203 chmod($ScriptFileName, 0777);
204 }
205
206 function SetupConfigurationFiles()
207 {
208 global $Config;
209
210 $EmulatorEtcDir = '../emulator/'.$this->Data['Database']['Emulator']['Id'].'/etc/';
211 $RealmEtcDir = '../realm/'.$this->Id.'/etc/';
212 $RealmLogDir = '../realm/'.$this->Id.'/log/';
213 if(!file_exists($RealmEtcDir)) mkdir($RealmEtcDir, 0777, true);
214 if(!file_exists($RealmLogDir)) mkdir($RealmLogDir, 0777, true);
215
216 // mangosd.conf
217 if(!file_exists($RealmEtcDir.'mangosd.conf'))
218 file_put_contents($RealmEtcDir.'mangosd.conf', file_get_contents($EmulatorEtcDir.'mangosd.conf.dist'));
219 $EmulatorConfig = new MangosConfigurationFile($this->Database);
220 $EmulatorConfig->Load($RealmEtcDir.'mangosd.conf');
221 $EmulatorConfig->ParameterList['RealmID'] = $this->Data['Id'];
222 $EmulatorConfig->ParameterList['LoginDatabaseInfo'] = 'localhost;3306;server'.$this->Data['Server'].';server'.$this->Data['Server'].';server'.$this->Data['Server'].'_realmd';
223 $EmulatorConfig->ParameterList['WorldDatabaseInfo'] = 'localhost;3306;server'.$this->Data['Server'].';server'.$this->Data['Server'].';realm'.$this->Id.'_mangos';
224 $EmulatorConfig->ParameterList['CharacterDatabaseInfo'] = 'localhost;3306;server'.$this->Data['Server'].';server'.$this->Data['Server'].';realm'.$this->Id.'_characters';
225 $EmulatorConfig->ParameterList['ScriptDev2DatabaseInfo'] = 'localhost;3306;server'.$this->Data['Server'].';server'.$this->Data['Server'].';realm'.$this->Id.'_scriptdev2';
226 $EmulatorConfig->ParameterList['WorldServerPort'] = $this->Data['NetworkPortWorldd'];
227 $EmulatorConfig->ParameterList['DataDir'] = 'wowclient/'.$this->Data['Database']['Emulator']['Client']['Version'];
228 $EmulatorConfig->ParameterList['LogsDir'] = 'realm/'.$this->Id.'/log';
229 $EmulatorConfig->ParameterList['LogLevel'] = 1;
230 $EmulatorConfig->ParameterList['LogSQL'] = 0;
231 $EmulatorConfig->Save($RealmEtcDir.'mangosd.conf');
232
233 // scriptdev2.conf
234 $EmulatorConfig = new MangosConfigurationFile($this->Database);
235 $EmulatorConfig->Load($EmulatorEtcDir.'scriptdev2.conf');
236 $EmulatorConfig->ParameterList['ScriptDev2DatabaseInfo'] = 'localhost;3306;server'.$this->Data['Server'].';server'.$this->Data['Server'].';realm'.$this->Id.'_scriptdev2';
237 $EmulatorConfig->Save($RealmEtcDir.'scriptdev2.conf');
238 }
239
240 function Update($DatabaseId, $DoBackup = true, $DoStop = true)
241 {
242 $this->Lock();
243 $Output = '';
244
245 // Stop server before update
246 if($DoStop)
247 {
248 $Output .= $this->Stop();
249 }
250
251 // Backup current
252 if($DoBackup)
253 {
254 $Backup = new Backup($this->Database, 0);
255 $Output .= '<br />'.$Backup->Create($this->Id);
256 }
257
258 // Do update
259 $Commands = array(
260 'php www/shell.php RealmLock '.$this->Id,
261 );
262 $DbResult = $this->Database->query('SELECT `Revision` FROM `Database` WHERE `Id` = '.$this->Data['Database']['Id']);
263 $DbRow = $DbResult->fetch_assoc();
264 $DatabaseRevisionStart = $DbRow['Revision'];
265 $DbResult = $this->Database->query('SELECT `Revision` FROM `Database` WHERE `Id` = '.$DatabaseId);
266 $DbRow = $DbResult->fetch_assoc();
267 $DatabaseRevisionEnd = $DbRow['Revision'];
268 $DbResult = $this->Database->query('SELECT * FROM `Database` WHERE (`Revision` > '.$DatabaseRevisionStart.') AND (`Revision` <= '.$DatabaseRevisionEnd.') ORDER BY `Revision`');
269 while($DbRow = $DbResult->fetch_assoc())
270 {
271 $Updates = explode("\n", $DbRow['Update']);
272 foreach($Updates as $Update)
273 if($Update != '')
274 {
275 $Parts = explode('|', $Update);
276 if($Parts[0] != 'realmd')
277 $Command = 'mysql --user=server'.$this->Data['Server'].' --password=server'.$this->Data['Server'].' realm'.$this->Id.'_'.$Parts[0].' < database/'.$DbRow['Id'].'/'.$Parts[1];
278 $Commands[] = $Command;
279 }
280 }
281 $Commands = array_merge($Commands, array(
282 'php www/shell.php RealmDatabaseChange '.$this->Id.' '.$DatabaseId,
283 'php www/shell.php RealmUnLock '.$this->Id,
284 ));
285
286 $this->Task->Add('Aktualizace databáze', $Commands);
287 $Output .= '<br />Úloha aktualizace serveru byla přidána do fronty.';
288 return($Output);
289 }
290
291 function Lock()
292 {
293 $this->Database->update('Realm', 'Id='.$this->Id, array('Lock' => 1));
294 }
295
296 function UnLock()
297 {
298 $this->Database->update('Realm', 'Id='.$this->Id, array('Lock' => 0));
299 }
300
301 function ChangeDatabaseId($Id)
302 {
303 $this->Database->update('Realm', 'Id='.$this->Id, array('Database' => $Id));
304 $this->SaveConfiguration();
305 }
306
307 function GetUsedMemory()
308 {
309 $Output = array();
310 if(isset($this->Data['Database']['Emulator']['Id']))
311 exec('ps aux|grep "emulator/'.$this->Data['Database']['Emulator']['Id'].'/bin/mangos-worldd -c realm/'.$this->Id.'/etc/mangosd.conf"| grep -v grep', $Output);
312 if(count($Output) > 0)
313 {
314 while(strpos($Output[0], ' ') > 0) $Output[0] = str_replace(' ', ' ', $Output[0]);
315 $Parts = explode(' ', $Output[0]);
316 return($Parts[4]);
317 } else return(0);
318 }
319
320 function ProcessLog()
321 {
322 $File = fopen('../realm/'.$this->Id.'/log/mangos-worldd.log', 'r');
323 while(true)
324 {
325 $Readers = array($File);
326 if(stream_select($Readers, $Writers=null, $Except=null, 0, 15) < 1)
327 {
328 continue;
329 } else
330 {
331 // read data from the fifo
332 $Data = fread($File, 1024);
333 echo($Data);
334 $this->Database->insert('RealmLog', array('Time' => 'NOW()', 'Realm' => $this->Id, 'Text' => $Data));
335 }
336 sleep(1);
337 }
338 fclose($File);
339 }
340
341 function GetUser()
342 {
343 $DbResult = $this->Database->select('Server', 'User', 'Id='.$this->Data['Server']);
344 $DbRow = $DbResult->fetch_assoc();
345 return($DbRow['User']);
346 }
347
348 function UpdateState()
349 {
350 $State = $this->GetState();
351 $this->Database->update('Realm', 'Id='.$this->Id, array(
352 'Online' => $State['Online'],
353 'CharacterOnlineCount' => $State['CharacterOnlineCount'],
354 'CharacterCount' => $State['CharacterCount'],
355 ));
356 }
357
358 function UpdateStateAll()
359 {
360 $DbResult = $this->Database->select('Realm', 'Id');
361 while($DbRow = $DbResult->fetch_assoc())
362 {
363 $Realm = new Realm($this->Database, $DbRow['Id']);
364 $Realm->UpdateState();
365 }
366 }
367}
368
369?>
Note: See TracBrowser for help on using the repository browser.