3 /**********************************************************************************
4 ** (c) Copyright 2002, Brenno J.S.A.A.F. de Winter, De Winter Information Solutions
5 ** This is free software; you can redistribute it and/or modify it under the
6 ** terms of the GNU General Public License, see the file COPYING.
7 ***********************************************************************************/
12 AUTHOR : Brenno J.S.A.A.F. de Winter
13 De Winter Information Solutions
14 COPYRIGHT : 2002 - De Winter Information Solutions,
15 Brenno J.S.A.A.F. de Winter
18 First : November 8th 2002
19 Gnucomo-0.0.3: December 6th 2002
21 $Log: gcm_daemon.php,v $
22 Revision 1.13 2003-08-14 10:22:42 arjen
25 Revision 1.12 2003/08/05 07:46:37 arjen
26 BUGFIX: Print an error message if a parameter does not have
29 Revision 1.11 2003/07/09 07:25:02 arjen
30 Gcm_daemon gathers statistics on parameters, notifications, etc. for all objects.
32 Revision 1.10 2003/03/29 08:33:58 arjen
33 In phpclasses/db.class.php: Added the database connection string as
34 an argument to the function copy_db_class.
35 Fixed the PHP member function db::db_connect(). The Postgres connection
36 string is now passed as an argument to that function.
38 Revision 1.9 2003/02/21 08:37:59 arjen
39 Added new table to the database: log_adv_daemon_email.
44 // $Id: gcm_daemon.php,v 1.13 2003-08-14 10:22:42 arjen Exp $
46 ini_set('include_path', '.:./classes:../phpclasses');
48 //Tell the log that we're up.
49 define_syslog_variables();
50 openlog("gnucomo", LOG_PID, LOG_DAEMON);
51 syslog(LOG_INFO, "gcm_daemon started");
53 require_once "gnucomo_config.php";
54 require_once "db.class.php";
55 require_once "gnucomo.process_log.php";
57 // Set the standard variables //
58 $project_name = "gnucomo"; //name of the entire project
59 $app_name = "gcm_daemon"; //name of the application running
60 $developrelease = "FALSE"; //Indicates if special debug settings are needed
61 $db_version = 42; //The db_version indicates what the level of
62 //the database should be. If the database is
63 //old an update will be generated.
64 $gcmd_version = 5; //This value indicates the active version of the gcm_daemon,
65 //which is saved in the database. Log records that were not
66 //recognized before will now be recognized. The version doesn't
67 //mean anything in the overall gnucomo project.
69 //Avoid time-limit issues
73 // Read the database settings //
74 $class_settings = new gnucomo_config();
75 $class_settings->read($project_name);
77 //Open an connection to the database
78 $dbms_type = $class_settings->find_parameter("database", "type");
79 $dbms_host = $class_settings->find_parameter("database", "host");
80 $dbms_name = $class_settings->find_parameter("database", "name");
81 $dbms_user = $class_settings->find_parameter("gcm_daemon", "user");
82 $dbms_password = $class_settings->find_parameter("gcm_daemon", "password");
84 db_select($dbms_type);
86 $dbms->db_host = $dbms_host;
87 $dbms->db_name = $dbms_name;
88 $dbms->db_user = $dbms_user;
89 $dbms->db_password = $dbms_password;
90 $dbms->db_connect($class_settings->database());
92 if ($dbms->have_db_connection() == "FALSE") {
93 exit ("Database connection failed.");
95 //The database connection has been made.
96 $dbms_working = copy_db_class($dbms, $class_settings->database());
99 //Verify if the database is up-to-date by checking the versionnumber
100 $local_sql = "SELECT setting_value FROM db_value WHERE setting = 'db_version' ";
101 $dbms->query($local_sql);
103 if ($dbms->fetch_row() == "TRUE") {
104 $active_version = $dbms->db_result_row[0];
106 //Update the database to the most recent version.
107 if ($active_version < $db_version) {
108 include ("gnucomo_db_version.php");
111 syslog (LOG_INFO, "Couldn't initialize database version. Is this a gnucomo database?");
112 die ("Couldn't initialize database version.\n");
115 //If there is a new gcm_daemon_version the logrecords that couldn't be understood can be
116 //reprocessed. For this reason processed is now changed to false again for not recognized
118 $local_sql = "SELECT setting_value FROM db_value WHERE setting = 'gcm_daemon_version'";
119 $dbms->query($local_sql);
121 if ($dbms->fetch_row() == "TRUE") {
122 if ($dbms->db_result_row[0] < $gcmd_version) {
123 //Reactive log-records that weren't understood earlier.
124 $local_sql = "UPDATE log SET processed = false WHERE logid NOT IN (SELECT DISTINCT logid FROM log_adv)";
125 $dbms->query($local_sql);
127 //Update de gcm_daemon version in the database
128 $local_sql = "UPDATE db_value SET setting_value = '".$gcmd_version;
129 $local_sql .= "' WHERE setting = 'gcm_daemon_version'";
130 $dbms->query($local_sql);
136 //Now we loop the tasks that we have to do.
141 // Gather the statistics for each object
143 $obj_result = $dbms->query("SELECT objectid FROM object");
144 for ($obj = 0; $obj < $dbms->num_rows($obj_result); $obj++)
146 $object = $dbms->fetch_object($obj_result, $obj);
147 echo "Gathering statistics for object " . $object->objectid . "\n";
148 GatherStatistics($object->objectid);
151 //At this place we start processing new log-lines
153 //notificationstats(); // This function is obsolete
154 find_notifications();
156 $keep_running = 'FALSE';
158 } while ($keep_running == 'TRUE');
160 //Tell the log that we're ending our efforts in a nice way
161 syslog (LOG_INFO, "gcm_daemon ended nicely");
163 function process_log () {
165 /* This function will walk through the log-records that haven't been processed
166 * first a snapshot will be created of a the non-processed records.
167 * sequentially each record will dealt with. By doing that changes will be made
168 * in several log_adv_xxx tables
173 global $dbms_working;
174 global $class_settings;
176 //Find records in log that still have to be processed.
178 $local_sql = "SELECT setting_value FROM db_value WHERE setting = 'log_processing'";
179 $dbms->query($local_sql);
181 if ($dbms->fetch_row() == "TRUE") {
182 $last_log = $dbms->db_result_row[0];
185 //Query the log-table
186 $local_sql = "SELECT * FROM log WHERE logid > CAST(".$last_log." AS BIGINT) order by logid";
187 $dbms->query($local_sql);
189 //Update the log-statistics in the object-table
190 $local_statistics_db = copy_db_class($dbms, $class_settings->database());
191 $local_findobject_db = copy_db_class($dbms, $class_settings->database());
194 $local_upper_row = $dbms->num_rows() + $last_log + 1;
195 $local_sql = "SELECT COUNT(logid), objectid from log WHERE logid > CAST(". $last_log .
196 " AS BIGINT) AND logid < CAST (" . $local_upper_row . " AS BIGINT) GROUP BY objectid";
197 $local_statistics_db->query ($local_sql);
200 for ($i = 1; $i <= $local_statistics_db->num_rows(); $i++) {
201 $local_object_row = $local_statistics_db->fetch_row();
202 $local_sql = "UPDATE object SET log_count = log_count + " .
203 $local_statistics_db->db_result_row[0] . " WHERE objectid = '" .
204 $local_statistics_db->db_result_row[1] . "'";
205 $local_findobject_db->query($local_sql);
210 if ($dbms->num_rows() > 0) {
212 //Create a database connection for changes in the database.
213 $dbms_changes = copy_db_class($dbms, $class_settings->database());
214 if ($dbms_changes->have_db_connection() == 'TRUE') {
217 $local_sql_statistics = "";
218 $local_object_os = "";
219 $local_object_os_version = "";
221 while ($local_counter < $dbms->num_rows()) {
223 $local_return_row = $dbms->fetch_row();
224 if ($local_return_row == 'TRUE') {
225 //Work on active rows
226 $local_log_id = $dbms->db_result_row[0];
228 $local_sql_findobject = "SELECT os, os_version FROM object WHERE objectid = '".$dbms->db_result_row[1]."'";
229 $local_findobject_db->query($local_sql_findobject);
230 $local_findobject_result = $local_findobject_db->fetch_row();
231 if ($local_findobject_result == 'TRUE') {
233 //Now work on the OS again
234 $local_object_os = $local_findobject_db->db_result_row[0];
235 if ($local_object_os == "") {
236 $local_object_os = "Linux";
237 $local_object_os_version = "Unknown assuming Linux";
239 $local_object_os_version = $local_findobject_db->db_result_row[1];
243 switch (strtolower($local_object_os)) {
245 $local_process_return = linux_log ();
248 syslog (LOG_INFO, "Couldn't find suitable OS for processing the logline");
252 if ($local_process_return <> 'TRUE') {
253 $local_process_return = 'FALSE';
264 //Register that the logrecords have been processed.
265 $local_sql = "UPDATE db_value SET setting_value = '".$local_log_id."' where setting = 'log_processing'";
266 $dbms->query($local_sql);
269 //Update the statistics for the object-table
273 syslog (LOG_INFO, "Couldn't clone database connection.");
274 die ("Couldn't reconnect to the database.\n");
281 * Update a single statistic for some object.
282 * If it does not yet exist, it will be created.
285 function UpdateStatistic($objectid, $name, $value)
289 $result = $dbms->query("SELECT objectid FROM object_statistics WHERE
290 objectid='$objectid' AND statname='$name'");
291 if ($dbms->num_rows() == 0)
293 $dbms->query("INSERT INTO object_statistics VALUES
294 ('$objectid', '$name', '$value')");
298 $dbms->query("UPDATE object_statistics SET statvalue='$value' WHERE
299 statname='$name' AND objectid='$objectid'");
304 * Gather the statistics for a single object ($objectid).
305 * We count the number of parameters, removed parameters, notifications
306 * closed notifications and log entries. The totals of these are
307 * maintained in a separate table: object_statistics.
310 function GatherStatistics($objectid)
314 // Gather statistics on parameters
316 $r = $dbms->query("SELECT paramid FROM parameter WHERE objectid=CAST('"
317 . $objectid . "' AS BIGINT)");
318 $nr_parameters = $dbms->num_rows($r);
320 $removed_parameters = 0;
321 for ($p = 0; $p < $nr_parameters; $p++)
323 $param = pg_fetch_object($r, $p);
324 $qry ="select change_nature from history where paramid= CAST('";
325 $qry .= $param->paramid . "' AS BIGINT) order by modified desc";
326 $rhist = $dbms->query($qry);
327 if ($dbms->num_rows($rhist) == 0)
329 echo "ERROR: No history for parameter id " . $param->paramid . "\n";
333 $hist = $dbms->fetch_object($rhist, 0);
334 if ($hist->change_nature == "REMOVED")
336 $removed_parameters++;
341 UpdateStatistic($objectid, 'parameters', $nr_parameters);
342 UpdateStatistic($objectid, 'removed_parameters', $removed_parameters);
344 // Gather statistics on notifications
346 $r = $dbms->query("SELECT count(notificationid) FROM notification WHERE
347 objectid = CAST('" . $objectid . "' AS BIGINT)");
348 $cnt = $dbms->fetch_object($r, 0);
349 UpdateStatistic($objectid, 'notifications', $cnt->count);
351 $r = $dbms->query("SELECT count(notificationid) FROM notification WHERE
352 objectid = CAST('" . $objectid . "' AS BIGINT) AND statuscode ='cls'");
353 $cnt = $dbms->fetch_object($r, 0);
354 UpdateStatistic($objectid, 'closed_notifications', $cnt->count);
356 // Gather statistics on log entries
358 $r = $dbms->query("SELECT count(logid) FROM log WHERE
359 objectid = CAST('" . $objectid . "' AS BIGINT)");
360 $cnt = $dbms->fetch_object($r, 0);
361 UpdateStatistic($objectid, 'logs', $cnt->count);
364 function notificationstats ()
369 /* This routine will determine how many new notifications have arrived and will
370 * update the statistics in the object-table to keep the performance acceptable
375 global $dbms, $class_settings;
377 //Find records in log that still have to be processed.
378 $local_sql = "SELECT setting_value FROM db_value WHERE setting = 'last_notification'";
379 $dbms->query($local_sql);
380 $local_dbms = copy_db_class($dbms, $class_settings->database());
382 //Determine the last notification
383 if ($dbms->fetch_row() == "TRUE") {
384 $last_notification = $dbms->db_result_row[0];
387 //Determine how many records we are going to analyse.
388 $local_sql = "SELECT MAX(notificationid) FROM notification " .
389 "WHERE notificationid > CAST ('" . $last_notification . "' AS BIGINT)";
390 $dbms->query($local_sql);
392 //Only process data if there are new notifications
393 if ($dbms->fetch_row() == "TRUE") {
394 if (intval($dbms->db_result_row[0])>0) {
395 $local_upper = $dbms->db_result_row[0] + 1;
396 $local_max = $dbms->db_result_row[0];
397 $local_sql = "SELECT COUNT(objectid), objectid FROM notification " .
398 "WHERE notificationid > CAST ('" . $last_notification ."' AS BIGINT) " .
399 "AND notificationid < CAST ('" . $local_upper .
400 "' AS BIGINT) GROUP BY objectid";
401 $dbms->query($local_sql);
404 for ($i=0; $i < $dbms->num_rows(); $i++) {
407 $local_sql = "UPDATE object SET notification_count = notification_count + " . $dbms->db_result_row[0] .
408 " WHERE objectid = '" . $dbms->db_result_row[1] . "'";
409 $local_dbms->query($local_sql);
412 $local_sql = "UPDATE db_value SET setting_value = '" . $local_max .
413 "' WHERE setting = 'last_notification'";
414 $dbms->query($local_sql);
419 function find_notifications () {
422 * Do something with notification checks.
430 //Find checks that have to be executed.
431 $local_sql = "select * from notification_check where age(last_execution) > time_between_executions";
432 $dbms->query($local_sql);
433 for ($i=0; $i<$dbms->num_rows(); $i++) {
434 //A check has been found that has to be executed