1<?php
2/*=========================================================================
3
4  Program:   CDash - Cross-Platform Dashboard System
5  Module:    $Id$
6  Language:  PHP
7  Date:      $Date$
8  Version:   $Revision$
9
10  Copyright (c) 2002 Kitware, Inc.  All rights reserved.
11  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12
13     This software is distributed WITHOUT ANY WARRANTY; without even
14     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15     PURPOSE.  See the above copyright notices for more information.
16
17=========================================================================*/
18require_once("cdash/defines.php");
19require_once("cdash/pdocore.php");
20require_once("models/errorlog.php");
21
22
23function cdash_unlink($filename)
24{
25  $success = unlink($filename);
26
27//  $try_count = 1;
28//
29//  while(file_exists($filename) && $try_count < 60)
30//  {
31//    usleep(1000000); // == 1000 ms, == 1.0 seconds
32//
33//    $success = unlink($filename);
34//    $try_count++;
35//  }
36
37  if (file_exists($filename))
38  {
39    throw new Exception("file still exists after unlink: $filename");
40  }
41
42  if (!$success)
43  {
44    throw new Exception("unlink returned non-success: $success for $filename");
45  }
46
47  return $success;
48}
49
50
51/** Add information to the log file */
52function add_log($text, $function, $type=LOG_INFO, $projectid=0, $buildid=0,
53                 $resourcetype=0, $resourceid=0)
54{
55  global $CDASH_LOG_FILE;
56  global $CDASH_LOG_FILE_MAXSIZE_MB;
57  global $CDASH_LOG_LEVEL;
58
59  // Check if we are within the log level
60  if($type!= LOG_TESTING && $type>$CDASH_LOG_LEVEL)
61    {
62    return;
63    }
64
65  $logFile = $CDASH_LOG_FILE;
66  if($buildid == 0 && isset($GLOBALS['PHP_ERROR_BUILD_ID'])) //use the global build id as a default if it's set
67    {
68    $buildid = $GLOBALS['PHP_ERROR_BUILD_ID'];
69    }
70
71  if(!file_exists(dirname($logFile)))
72    {
73    $paths = explode(PATH_SEPARATOR, get_include_path());
74    // Search the include path for the log file
75    foreach($paths as $path)
76      {
77      if(file_exists(dirname("$path/$CDASH_LOG_FILE")))
78        {
79        $logFile = "$path/$CDASH_LOG_FILE";
80        break;
81        }
82      }
83    }
84
85  if(strlen($text)==0)
86    {
87    return;
88    }
89
90  // If the size of the log file is bigger than 10 times the allocated memory
91  // we rotate
92  $maxlogsize = $CDASH_LOG_FILE_MAXSIZE_MB*1024*1024/10.0;
93  if(file_exists($logFile) && filesize($logFile)>$maxlogsize)
94    {
95    $tmplogfile = $logFile.".tmp";
96    if(!file_exists($tmplogfile))
97      {
98      rename($logFile,$tmplogfile); // This should be quick so we can keep logging
99
100      for($i=9;$i>=0;$i--)
101        {
102        // If we don't have compression we just rename the files
103        if(!function_exists("gzwrite"))
104          {
105          $currentfile = $logFile.".".$i.".txt";
106          $j = $i+1;
107          $newfile = $logFile.".".$j.".txt";
108          if(file_exists($newfile))
109            {
110            cdash_unlink($newfile);
111            }
112          if(file_exists($currentfile))
113            {
114            rename($currentfile,$newfile);
115            }
116          }
117        else
118          {
119          $currentfile = $logFile.".".$i.".gz";
120          $j = $i+1;
121          $newfile = $logFile.".".$j.".gz";
122          if(file_exists($newfile))
123            {
124            cdash_unlink($newfile);
125            }
126          if(file_exists($currentfile))
127            {
128            $gz = gzopen($newfile,'wb');
129            $f = fopen($currentfile,'rb');
130            while($f && !feof($f))
131              {
132              gzwrite($gz, fread($f, 8192));
133              }
134            fclose($f);
135            unset($f);
136            gzclose($gz);
137            unset($gz);
138            }
139          }
140        }
141
142      // Move the current backup
143      if(!function_exists("gzwrite"))
144        {
145        rename($tmplogfile,$logFile.'.0.txt');
146        }
147      else
148        {
149        $gz = gzopen($logFile.'.0.gz','wb');
150        $f = fopen($tmplogfile,'rb');
151        while($f && !feof($f))
152          {
153          gzwrite($gz, fread($f, 8192));
154          }
155        fclose($f);
156        unset($f);
157        gzclose($gz);
158        unset($gz);
159        cdash_unlink($tmplogfile);
160        }
161      } // end tmp file doesn't exist
162    } // end log rotation
163
164  $error = "";
165  if($type != LOG_TESTING)
166    {
167    $error = "[".date(FMT_DATETIME)."]";
168    }
169
170  // This is parsed by the testing
171  switch($type)
172    {
173    case LOG_INFO: $error.="[INFO]"; break;
174    case LOG_WARNING: $error.="[WARNING]"; break;
175    case LOG_ERR: $error.="[ERROR]"; break;
176    case LOG_TESTING: $error.="[TESTING]";break;
177    }
178  $error .= "[pid=".getmypid()."]";
179  $error .= "(".$function."): ".$text."\n";
180
181  $log_pre_exists = file_exists($logFile);
182
183  $logged = error_log($error, 3, $logFile);
184
185  // If there was a problem logging to cdash.log, echo and send it to
186  // PHP's system log:
187  //
188  if (!$logged)
189    {
190    echo "warning: problem logging error to $logFile\n";
191    echo "  $error\n";
192    echo "\n";
193    echo "attempting to send to PHP's system log now\n";
194    echo "\n";
195
196    error_log($error, 0);
197    }
198
199  // If we just created the logFile, then give it group write permissions
200  // so that command-line invocations of CDash functions can also write to
201  // the same log file.
202  //
203  if (!$log_pre_exists && $logged && file_exists($logFile))
204    {
205    chmod($logFile, 0664);
206    }
207
208  // Insert in the database
209  if($type == LOG_WARNING || $type==LOG_ERR)
210    {
211    $ErrorLog = new ErrorLog;
212    $ErrorLog->ProjectId = $projectid;
213    $ErrorLog->BuildId = $buildid;
214    switch($type)
215      {
216      // case LOG_INFO: $ErrorLog->Type = 6; break;
217      case LOG_WARNING: $ErrorLog->Type = 5; break;
218      case LOG_ERR: $ErrorLog->Type = 4; break;
219      }
220    $ErrorLog->Description = "(".$function."): ".$text;
221    $ErrorLog->ResourceType = $resourcetype;
222    $ErrorLog->ResourceId = $resourceid;
223
224    $ErrorLog->Insert();
225    }
226}
227
228
229function begin_timer($context)
230{
231  global $cdash_timer_stack;
232  if (!isset($cdash_timer_stack))
233    {
234    $cdash_timer_stack = array();
235    }
236
237  $timer_entry = array();
238  $timer_entry[] = $context;
239  $timer_entry[] = microtime_float();
240
241  $cdash_timer_stack[] = $timer_entry;
242}
243
244
245function end_timer($context, $threshold = -0.001)
246{
247  global $cdash_timer_stack;
248  if (!isset($cdash_timer_stack))
249    {
250    trigger_error(
251      'end_timer called before begin_timer',
252      E_USER_WARNING);
253    }
254
255  $end_time = microtime_float();
256
257  $n = count($cdash_timer_stack)-1;
258  $timer_entry = $cdash_timer_stack[$n];
259  $begin_context = $timer_entry[0];
260  $begin_time = $timer_entry[1];
261
262  if ($context != $begin_context)
263    {
264    trigger_error(
265      'end_timer called with different context than begin_timer',
266      E_USER_WARNING);
267    }
268
269  array_pop($cdash_timer_stack);
270
271  $text = '';
272  for($i = 0; $i < $n; ++$i)
273    {
274    $text .= '  ';
275    }
276
277  $delta = $end_time - $begin_time;
278
279  $text .= $context . ', ' . round($delta, 3) . ' seconds';
280
281  if ($delta > $threshold)
282    {
283    add_log($text, "end_timer");
284    }
285}
286?>
287