PageRenderTime 66ms CodeModel.GetById 36ms RepoModel.GetById 0ms app.codeStats 1ms

/inc/dbconnection.class.php

https://github.com/ardowz/Thesis-SideB
PHP | 431 lines | 245 code | 72 blank | 114 comment | 42 complexity | df762a27d6c31b2dec056e652aefb7aa MD5 | raw file
  1. <?php
  2. /*
  3. * @version $Id: dbconnection.class.php 14834 2011-07-01 14:09:28Z remi $
  4. -------------------------------------------------------------------------
  5. GLPI - Gestionnaire Libre de Parc Informatique
  6. Copyright (C) 2003-2011 by the INDEPNET Development Team.
  7. http://indepnet.net/ http://glpi-project.org
  8. -------------------------------------------------------------------------
  9. LICENSE
  10. This file is part of GLPI.
  11. GLPI is free software; you can redistribute it and/or modify
  12. it under the terms of the GNU General Public License as published by
  13. the Free Software Foundation; either version 2 of the License, or
  14. (at your option) any later version.
  15. GLPI is distributed in the hope that it will be useful,
  16. but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. GNU General Public License for more details.
  19. You should have received a copy of the GNU General Public License
  20. along with GLPI; if not, write to the Free Software Foundation, Inc.,
  21. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  22. --------------------------------------------------------------------------
  23. */
  24. if (!defined('GLPI_ROOT')) {
  25. die("Sorry. You can't access directly to this file");
  26. }
  27. /**
  28. * Database class for Mysql
  29. **/
  30. class DBConnection extends CommonDBTM {
  31. var $notable = true;
  32. static function getTypeName() {
  33. global $LANG;
  34. return $LANG['setup'][800];
  35. }
  36. /**
  37. * Create slave DB configuration file
  38. *
  39. * @param host the slave DB host(s)
  40. * @param user the slave DB user
  41. * @param password the slave DB password
  42. * @param DBname the name of the slave DB
  43. *
  44. * @return boolean for success
  45. **/
  46. static function createSlaveConnectionFile($host, $user, $password, $DBname) {
  47. $DB_str = "<?php \n class DBSlave extends DBmysql { \n var \$slave = true; \n var \$dbhost = ";
  48. $host = trim($host);
  49. if (strpos($host, ' ')) {
  50. $hosts = explode(' ', $host);
  51. $first = true;
  52. foreach ($hosts as $host) {
  53. if (!empty($host)) {
  54. $DB_str .= ($first ? "array('" : ",'").$host."'";
  55. $first = false;
  56. }
  57. }
  58. if ($first) {
  59. // no host configured
  60. return false;
  61. }
  62. $DB_str .= ");\n";
  63. } else {
  64. $DB_str .= "'$host';\n";
  65. }
  66. $DB_str .= " var \$dbuser = '" . $user . "'; \n var \$dbpassword= '" .
  67. rawurlencode($password) . "'; \n var \$dbdefault = '" . $DBname . "'; \n } \n ?>";
  68. $fp = fopen(GLPI_CONFIG_DIR . "/config_db_slave.php", 'wt');
  69. if ($fp) {
  70. $fw = fwrite($fp, $DB_str);
  71. fclose($fp);
  72. return true;
  73. }
  74. return false;
  75. }
  76. /**
  77. * Indicates is the DB replicate is active or not
  78. *
  79. * @return true if active / false if not active
  80. **/
  81. static function isDBSlaveActive() {
  82. return file_exists(GLPI_CONFIG_DIR . "/config_db_slave.php");
  83. }
  84. /**
  85. * Read slave DB configuration file
  86. *
  87. * @param $choice integer, host number
  88. *
  89. * @return DBmysql object
  90. **/
  91. static function getDBSlaveConf($choice=NULL) {
  92. if (self::isDBSlaveActive()) {
  93. include_once (GLPI_CONFIG_DIR . "/config_db_slave.php");
  94. return new DBSlave($choice);
  95. }
  96. }
  97. /**
  98. * Create a default slave DB configuration file
  99. **/
  100. static function createDBSlaveConfig() {
  101. self::createSlaveConnectionFile("localhost", "glpi", "glpi", "glpi");
  102. }
  103. /**
  104. * Save changes to the slave DB configuration file
  105. **/
  106. static function saveDBSlaveConf($host, $user, $password, $DBname) {
  107. self::createSlaveConnectionFile($host, $user, $password, $DBname);
  108. }
  109. /**
  110. * Delete slave DB configuration file
  111. */
  112. static function deleteDBSlaveConfig() {
  113. unlink(GLPI_CONFIG_DIR . "/config_db_slave.php");
  114. }
  115. /**
  116. * Switch database connection to slave
  117. **/
  118. static function switchToSlave() {
  119. global $DB;
  120. if (self::isDBSlaveActive()) {
  121. include_once (GLPI_CONFIG_DIR . "/config_db_slave.php");
  122. $DB = new DBSlave;
  123. return $DB->connected;
  124. }
  125. return false;
  126. }
  127. /**
  128. * Switch database connection to master
  129. **/
  130. static function switchToMaster() {
  131. global $DB;
  132. $DB = new DB;
  133. return $DB->connected;
  134. }
  135. /**
  136. * Get Connection to slave, if exists,
  137. * and if configured to be used for read only request
  138. *
  139. * @return DBmysql object
  140. **/
  141. static function getReadConnection() {
  142. global $DB, $CFG_GLPI;
  143. if ($CFG_GLPI['use_slave_for_search']
  144. && !$DB->isSlave()
  145. && self::isDBSlaveActive()) {
  146. include_once (GLPI_CONFIG_DIR . "/config_db_slave.php");
  147. $DBread = new DBSlave();
  148. if ($DBread->connected) {
  149. return $DBread;
  150. }
  151. }
  152. return $DB;
  153. }
  154. /**
  155. * Establish a connection to a mysql server (main or replicate)
  156. *
  157. * @param $use_slave try to connect to slave server first not to main server
  158. * @param $required connection to the specified server is required
  159. * (if connection failed, do not try to connect to the other server)
  160. * @param $display display error message
  161. **/
  162. static function establishDBConnection($use_slave, $required, $display=true) {
  163. global $DB;
  164. $DB = null;
  165. $res = false;
  166. // First standard config : no use slave : try to connect to master
  167. if (!$use_slave) {
  168. $res = self::switchToMaster();
  169. }
  170. // If not already connected to master due to config or error
  171. if (!$res) {
  172. // No DB slave : first connection to master give error
  173. if (!self::isDBSlaveActive()) {
  174. // Slave wanted but not defined -> use master
  175. // Ignore $required when no slave configured
  176. if ($use_slave) {
  177. $res = self::switchToMaster();
  178. }
  179. // Slave DB configured
  180. } else {
  181. // Try to connect to slave if wanted
  182. if ($use_slave) {
  183. $res = self::switchToSlave();
  184. }
  185. // No connection to 'mandatory' server
  186. if (!$res && !$required) {
  187. //Try to establish the connection to the other mysql server
  188. if ($use_slave) {
  189. $res = self::switchToMaster();
  190. } else {
  191. $res = self::switchToSlave();
  192. }
  193. if ($res) {
  194. $DB->first_connection=false;
  195. }
  196. }
  197. }
  198. }
  199. // Display error if needed
  200. if (!$res && $display) {
  201. self::displayMySQLError();
  202. }
  203. return $res;
  204. }
  205. /**
  206. * Get delay between slave and master
  207. *
  208. * @param $choice integer, host number
  209. *
  210. * @return integer
  211. **/
  212. static function getReplicateDelay($choice=NULL) {
  213. include_once (GLPI_CONFIG_DIR . "/config_db_slave.php");
  214. return (int) (self::getHistoryMaxDate(new DB())
  215. - self::getHistoryMaxDate(new DBSlave($choice)));
  216. }
  217. /**
  218. * Get history max date of a GLPI DB
  219. *
  220. * @param $DBconnection DB conneciton used
  221. **/
  222. static function getHistoryMaxDate($DBconnection) {
  223. if ($DBconnection->connected) {
  224. $result = $DBconnection->query("SELECT UNIX_TIMESTAMP(MAX(`date_mod`)) AS max_date
  225. FROM `glpi_logs`");
  226. if ($DBconnection->numrows($result) > 0) {
  227. return $DBconnection->result($result, 0, "max_date");
  228. }
  229. }
  230. return 0;
  231. }
  232. /**
  233. * Display a common mysql connection error
  234. **/
  235. static function displayMySQLError() {
  236. nullHeader("Mysql Error", '');
  237. if (!isCommandLine()) {
  238. echo "<div class='center'><p><strong>
  239. A link to the Mysql server could not be established. Please check your configuration.
  240. </strong></p><p><strong>
  241. Le serveur Mysql est inaccessible. V&eacute;rifiez votre configuration</strong></p>
  242. </div>";
  243. } else {
  244. echo "A link to the Mysql server could not be established. Please check your configuration.\n";
  245. echo "Le serveur Mysql est inaccessible. V&eacute;rifiez votre configuration\n";
  246. }
  247. nullFooter();
  248. die();
  249. }
  250. static function cronInfo($name) {
  251. global $LANG;
  252. return array('description' => $LANG['crontask'][10],
  253. 'parameter' => $LANG['setup'][806]);
  254. }
  255. /**
  256. * Cron process to check DB replicate state
  257. *
  258. * @param $task to log and get param
  259. **/
  260. static function cronCheckDBreplicate($task) {
  261. global $DB, $LANG;
  262. //Lauch cron only is :
  263. // 1 the master database is avalaible
  264. // 2 the slave database is configurated
  265. if (!$DB->isSlave() && self::isDBSlaveActive()) {
  266. $DBslave = self::getDBSlaveConf();
  267. if (is_array($DBslave->dbhost)) {
  268. $hosts = $DBslave->dbhost;
  269. } else {
  270. $hosts = array($DBslave->dbhost);
  271. }
  272. foreach ($hosts as $num => $name) {
  273. $diff = self::getReplicateDelay($num);
  274. // Quite strange, but allow simple stat
  275. $task->addVolume($diff);
  276. if ($diff > 1000000000) { // very large means slave is disconnect
  277. $task->log($LANG['install'][30]." : '$name', ".$LANG['install'][35]);
  278. } else {
  279. $task->log($LANG['install'][30]." : '$name', ".
  280. $LANG['setup'][803]." : ".timestampToString($diff, true));
  281. }
  282. if ($diff > ($task->fields['param']*60)) {
  283. //Raise event if replicate is not synchronized
  284. $options = array('diff' => $diff,
  285. 'name' => $name,
  286. 'entities_id' => 0); // entity to avoid warning in getReplyTo
  287. NotificationEvent::raiseEvent('desynchronization', new self(), $options);
  288. }
  289. }
  290. return 1;
  291. }
  292. return 0;
  293. }
  294. /**
  295. * Display in HTML, delay between master and slave
  296. * 1 line per slave is multiple
  297. **/
  298. static function showAllReplicateDelay() {
  299. global $LANG;
  300. $DBSlave = self::getDBSlaveConf();
  301. if (is_array($DBSlave->dbhost)) {
  302. $hosts = $DBSlave->dbhost;
  303. } else {
  304. $hosts = array($DBslave->dbhost);
  305. }
  306. foreach ($hosts as $num => $name) {
  307. $diff = self::getReplicateDelay($num);
  308. echo $LANG['install'][30] . "&nbsp;: '$name', ";
  309. if ($diff > 1000000000) {
  310. echo $LANG['install'][35] . "<br>";
  311. } else if ($diff) {
  312. echo $LANG['setup'][803] . "&nbsp;: " . timestampToString($diff, 1) . "<br>";
  313. } else {
  314. echo $LANG['setup'][803] . "&nbsp;: " . $LANG['common'][49] . "<br>";
  315. }
  316. }
  317. }
  318. function showSystemInformations($width) {
  319. global $LANG;
  320. echo "\n</pre></td>";
  321. echo "</tr><tr class='tab_bg_2'><th>" . $LANG['setup'][800] . "</th></tr>";
  322. echo "<tr class='tab_bg_1'><td><pre>\n&nbsp;\n";
  323. if (self::isDBSlaveActive()) {
  324. echo $LANG['common'][60]."&nbsp;: ".$LANG['choice'][1]." \n";
  325. self::showAllReplicateDelay();
  326. } else {
  327. echo $LANG['common'][60]."&nbsp;: ".$LANG['choice'][0]."\n";
  328. }
  329. echo "\n</pre></td></tr>";
  330. }
  331. /**
  332. * Enable or disable db replication check cron task
  333. *
  334. * @param enable of disable cron task
  335. **/
  336. static function changeCronTaskStatus($enable=true) {
  337. $cron = new CronTask;
  338. $cron->getFromDBbyName('DBConnection', 'CheckDBreplicate');
  339. $input['id'] = $cron->fields['id'];
  340. $input['state'] = ($enable?1:0);
  341. $cron->update($input);
  342. }
  343. }
  344. ?>