source: trunk/www/Module/Realm/Model.php

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