c83c65497108e0f41ba25bb379c5740791ad7183
[gnucomo.git] / src / gcm_daemon / gcm_daemon.php
1 #!/usr/bin/php
2 <?PHP
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 ***********************************************************************************/
8
9
10 /* 
11    NAME         : gcm_daemon
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
16    
17    * DATES * 
18    First        : November 8th 2002
19    Gnucomo-0.0.3: December 6th 2002
20
21  $Log: gcm_daemon.php,v $
22  Revision 1.10  2003-03-29 08:33:58  arjen
23  In phpclasses/db.class.php: Added the database connection string as
24  an argument to the function copy_db_class.
25  Fixed the PHP member function db::db_connect(). The Postgres connection
26  string is now passed as an argument to that function.
27
28  Revision 1.9  2003/02/21 08:37:59  arjen
29  Added new table to the database: log_adv_daemon_email.
30
31
32 */
33
34 // $Id: gcm_daemon.php,v 1.10 2003-03-29 08:33:58 arjen Exp $
35
36 ini_set('include_path', '.:./classes:../phpclasses');
37
38 //Tell the log that we're up.
39 define_syslog_variables();
40 openlog("gnucomo", LOG_PID, LOG_DAEMON);
41 syslog(LOG_INFO, "gcm_daemon started");
42
43 require_once "gnucomo_config.php";
44 require_once "db.class.php";
45 require_once "gnucomo.process_log.php";
46
47 // Set the standard variables //
48 $project_name   = "gnucomo";    //name of the entire project
49 $app_name       = "gcm_daemon"; //name of the application running
50 $developrelease = "TRUE";      //Indicates if special debug settings are needed
51 $db_version     = 36;           //The db_version indicates what the level of 
52                                 //the database should be. If the database is 
53                                 //old an update will be generated.
54 $gcmd_version   = 3;            //This value indicates the active version of the gcm_daemon,
55                                 //which is saved in the database. Log records that were not
56                                 //recognized before will now be recognized. The version doesn't
57                                 //mean anything in the overall gnucomo project.
58
59 //Avoid time-limit issues
60 set_time_limit(0);
61
62
63 // Read the database settings //
64 $class_settings = new gnucomo_config();
65 $class_settings->read($project_name);
66
67 //Open an connection to the database
68 $dbms_type = $class_settings->find_parameter("database", "type");
69 $dbms_host = $class_settings->find_parameter("database", "host");
70 $dbms_name = $class_settings->find_parameter("database", "name");
71 $dbms_user = $class_settings->find_parameter("gcm_daemon", "user");
72 $dbms_password = $class_settings->find_parameter("gcm_daemon", "password");
73
74 db_select($dbms_type);
75 $dbms = new db();
76 $dbms->db_host = $dbms_host;
77 $dbms->db_name = $dbms_name;
78 $dbms->db_user = $dbms_user;
79 $dbms->db_password = $dbms_password;
80 $dbms->db_connect($class_settings->database());
81
82 if ($dbms->have_db_connection() == "FALSE") {
83   exit ("Database connection failed.");
84 } else {
85   //The database connection has been made.
86   $dbms_working = copy_db_class($dbms, $class_settings->database());
87 }
88
89 //Verify if the database is up-to-date by checking the versionnumber
90 $local_sql = "SELECT setting_value FROM db_value WHERE setting = 'db_version' ";
91 $dbms->query($local_sql);
92
93 if ($dbms->fetch_row() == "TRUE") {
94   $active_version = $dbms->db_result_row[0];
95  
96   //Update the database to the most recent version.
97   if ($active_version < $db_version) { 
98      include ("gnucomo_db_version.php");
99   }
100 } else {
101   syslog (LOG_INFO, "Couldn't initialize database version. Is this a gnucomo database?");
102   die ("Couldn't initialize database version.\n");
103 }
104
105 //If there is a new gcm_daemon_version the logrecords that couldn't be understood can be
106 //reprocessed. For this reason processed is now changed to false again for not recognized
107 //records.
108 $local_sql = "SELECT setting_value FROM db_value WHERE setting = 'gcm_daemon_version'";
109 $dbms->query($local_sql);
110
111 if ($dbms->fetch_row() == "TRUE") {
112    if ($dbms->db_result_row[0] < $gcmd_version) {
113       //Reactive log-records that weren't understood earlier.
114       $local_sql = "UPDATE log SET processed = false WHERE logid NOT IN (SELECT DISTINCT logid FROM log_adv)";
115       $dbms->query($local_sql);
116
117       //Update de gcm_daemon version in the database
118       $local_sql = "UPDATE db_value SET setting_value = '".$gcmd_version;
119       $local_sql .= "' WHERE setting = 'gcm_daemon_version'";
120       $dbms->query($local_sql);
121
122    }
123       
124 }
125
126 //Now we loop the tasks that we have to do.
127
128
129 do {
130
131   //At this place we start processing new log-lines 
132   process_log ();
133   notificationstats();
134
135   $keep_running = 'FALSE';
136
137 } while ($keep_running == 'TRUE');
138
139 //Tell the log that we're ending our efforts in a nice way
140 syslog (LOG_INFO, "gcm_daemon ended nicely");
141
142 function process_log () {
143  
144  /* This function will walk through the log-records that haven't been processed
145   * first a snapshot will be created of a the non-processed records. 
146   * sequentially each record will dealt with. By doing that changes will be made
147   * in several log_adv_xxx tables
148   * INPUT  : NONE
149   * OUTPUT : NONE
150   */
151   global $dbms;
152   global $dbms_working;
153   global $class_settings;
154
155   //Find records in log that still have to be processed.
156
157   $local_sql = "SELECT setting_value FROM db_value WHERE setting = 'log_processing'";
158   $dbms->query($local_sql);
159
160   if ($dbms->fetch_row() == "TRUE") {
161      $last_log = $dbms->db_result_row[0];
162   }
163   
164   //Query the log-table
165   $local_sql = "SELECT * FROM log WHERE logid > CAST(".$last_log." AS BIGINT) order by logid";
166   $dbms->query($local_sql);
167
168   //Update the log-statistics in the object-table 
169   $local_statistics_db = copy_db_class($dbms, $class_settings->database());
170   $local_findobject_db = copy_db_class($dbms, $class_settings->database());
171
172   //Make totals 
173   $local_upper_row = $dbms->num_rows() + $last_log + 1;
174   $local_sql = "SELECT COUNT(logid), objectid from log WHERE logid > CAST(". $last_log .
175       " AS BIGINT) AND logid < CAST (" . $local_upper_row . " AS BIGINT) GROUP BY objectid";
176   $local_statistics_db->query ($local_sql);
177
178   //Loop the objects
179   for ($i = 1; $i <= $local_statistics_db->num_rows(); $i++) {
180       $local_object_row = $local_statistics_db->fetch_row();
181       $local_sql = "UPDATE object SET log_count = log_count + " . 
182           $local_statistics_db->db_result_row[0] . " WHERE objectid = '" .
183           $local_statistics_db->db_result_row[1] . "'";
184       $local_findobject_db->query($local_sql);  
185   }
186
187   $local_counter = 0;
188
189   if ($dbms->num_rows() > 0) {
190
191     //Create a database connection for changes in the database.
192     $dbms_changes = copy_db_class($dbms, $class_settings->database());
193     if ($dbms_changes->have_db_connection() == 'TRUE') {
194
195        $local_sql               = 0 ;     
196        $local_sql_statistics    = "";
197        $local_object_os         = "";
198        $local_object_os_version = "";
199
200        while ($local_counter < $dbms->num_rows()) {
201
202          $local_return_row = $dbms->fetch_row();
203          if ($local_return_row == 'TRUE') {
204             //Work on active rows
205             $local_log_id = $dbms->db_result_row[0];
206
207             $local_sql_findobject = "SELECT os, os_version FROM object WHERE objectid = '".$dbms->db_result_row[1]."'";
208             $local_findobject_db->query($local_sql_findobject);
209             $local_findobject_result = $local_findobject_db->fetch_row();
210             if ($local_findobject_result == 'TRUE') {
211                 
212                 //Now work on the OS again
213                 $local_object_os = $local_findobject_db->db_result_row[0];
214                 if  ($local_object_os == "") {
215                     $local_object_os = "Linux";
216                     $local_object_os_version = "Unknown assuming Linux";
217                 } else {
218                   $local_object_os_version = $local_findobject_db->db_result_row[1];
219                 }
220              }
221
222             switch (strtolower($local_object_os)) {
223               case "linux":
224                 $local_process_return = linux_log ();
225                 break;
226               default:
227                 syslog (LOG_INFO, "Couldn't find suitable OS for processing the logline");
228                 break;
229              }
230             
231             if ($local_process_return <> 'TRUE') {
232                $local_process_return = 'FALSE';
233             }
234
235          } else {
236
237            break;
238
239          }
240          $local_counter++;
241        } 
242        
243        //Register that the logrecords have been processed.
244        $local_sql = "UPDATE db_value SET setting_value = '".$local_log_id."' where setting = 'log_processing'";
245        $dbms->query($local_sql);
246        
247
248        //Update the statistics for the object-table
249        
250
251      } else {
252        syslog (LOG_INFO, "Couldn't clone database connection.");
253        die ("Couldn't reconnect to the database.\n");
254     }     
255    }
256
257 }
258
259 function notificationstats () {
260
261 /* This routine will determine how many new notifications have arrived and will
262  * update the statistics in the object-table to keep the performance acceptable
263  * INPUT  : NONE
264  * OUTPUT : NONE
265  */
266             
267  global $dbms, $class_settings;
268
269  //Find records in log that still have to be processed.
270  $local_sql = "SELECT setting_value FROM db_value WHERE setting = 'last_notification'";
271  $dbms->query($local_sql);
272  $local_dbms = copy_db_class($dbms, $class_settings->database());
273
274  //Determine the last notification
275  if ($dbms->fetch_row() == "TRUE") {
276     $last_notification = $dbms->db_result_row[0];
277  }
278  
279  //Determine how many records we are going to analyse.
280  $local_sql = "SELECT MAX(notificationid) FROM notification " .
281    "WHERE notificationid > CAST ('" . $last_notification . "' AS BIGINT)";
282  $dbms->query($local_sql);  
283
284  //Only process data if there are new notifications
285  if ($dbms->fetch_row() == "TRUE") {
286   if (intval($dbms->db_result_row[0])>0) {
287      $local_upper = $dbms->db_result_row[0] + 1;
288      $local_max   = $dbms->db_result_row[0];
289      $local_sql   = "SELECT COUNT(objectid), objectid FROM notification " .
290        "WHERE notificationid > CAST ('" .  $last_notification ."' AS BIGINT) " .
291        "AND   notificationid < CAST ('" .  $local_upper .
292        "' AS BIGINT) GROUP BY objectid";
293      $dbms->query($local_sql);
294
295
296      for ($i=0; $i < $dbms->num_rows(); $i++) {
297        $dbms->fetch_row();
298     
299        $local_sql = "UPDATE object SET notification_count = notification_count + " . $dbms->db_result_row[0] .
300          " WHERE objectid = '" . $dbms->db_result_row[1] . "'";
301       $local_dbms->query($local_sql); 
302      }  
303
304      $local_sql = "UPDATE db_value SET setting_value = '" . $local_max . 
305        "' WHERE setting = 'last_notification'";
306      $dbms->query($local_sql);  
307   }   
308  } 
309 }
310
311 ?>
312