瀏覽代碼

implement log_history functionality

Ken Patel 16 年之前
父節點
當前提交
8dc84e42d8
共有 3 個文件被更改,包括 130 次插入3 次删除
  1. 82 2
      direct/src/plugin/p3dMainObject.cxx
  2. 44 0
      direct/src/plugin/p3dSession.cxx
  3. 4 1
      direct/src/plugin/p3d_plugin.h

+ 82 - 2
direct/src/plugin/p3dMainObject.cxx

@@ -450,9 +450,11 @@ call_read_log(P3D_object *params[], int num_params) {
 ////////////////////////////////////////////////////////////////////
 P3D_object *P3DMainObject::
 read_log(const string &log_pathname, P3D_object *params[], int num_params) {
+  P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
+  string log_directory = inst_mgr->get_log_directory();
+
   ifstream log(log_pathname.c_str(), ios::in);
   if (!log) {
-    P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
     return inst_mgr->new_undefined_object();
   }
 
@@ -470,6 +472,49 @@ read_log(const string &log_pathname, P3D_object *params[], int num_params) {
     head_bytes = (size_t)max(P3D_OBJECT_GET_INT(params[1]), 0);
   }
 
+  // Check if we want data from previous logs
+  const char log_sep_line_char = '-';
+  const int log_sep_line_chars = 80;
+  const int log_sep_filename_chars = 256;
+  const int log_sep_bytes = log_sep_line_chars + log_sep_filename_chars + 16;
+  size_t tail_bytes_prev = 0;
+  vector<string> log_basenames_prev;
+  if (num_params > 2) {
+    // Determine the base of the log file names
+    tail_bytes_prev = (size_t)max(P3D_OBJECT_GET_INT(params[2]), 0);
+    if (tail_bytes_prev > 0) {
+      string log_basename = log_pathname;
+      size_t slash = log_basename.rfind('/');
+      if (slash != string::npos) {
+        log_basename = log_basename.substr(slash + 1);
+      }
+#ifdef _WIN32
+      slash = log_basename.rfind('\\');
+      if (slash != string::npos) {
+        log_basename = log_basename.substr(slash + 1);
+      }
+#endif  // _WIN32
+      string log_basename_curr = log_basename;
+      int dash = log_basename.rfind("-");
+      if (dash != string::npos) {
+        log_basename = log_basename.substr(0, dash+1);
+
+        // Find matching files
+        vector<string> all_logs;
+        inst_mgr->scan_directory(log_directory, all_logs);
+        for (int i=0; i<(int)all_logs.size(); ++i) {
+          if ((all_logs[i].size() > 4) &&
+              (all_logs[i].find(log_basename) == 0) &&
+              (all_logs[i].substr(all_logs[i].size() - 4) == string(".log"))) {
+            if (all_logs[i] != log_basename_curr) {
+              log_basenames_prev.push_back(all_logs[i]);
+            }
+          }
+        }
+      }
+    }
+  }
+
   // Get the size of the file.
   log.seekg(0, ios::end);
   size_t file_size = (size_t)log.tellg();
@@ -500,6 +545,12 @@ read_log(const string &log_pathname, P3D_object *params[], int num_params) {
     return_size = head_bytes + separator.size() + tail_bytes;
   }
 
+  // We will need additional space for data from previous logs
+  if ((tail_bytes_prev > 0) && (log_basenames_prev.size() > 0)) {
+      int extra_bytes_per_prev_log = tail_bytes_prev + log_sep_bytes;
+      return_size += log_basenames_prev.size() * extra_bytes_per_prev_log;
+  }
+
   nout << "allocating " << return_size << " bytes to return.\n";
   char *buffer = new char[return_size];
   if (buffer == NULL) {
@@ -524,11 +575,40 @@ read_log(const string &log_pathname, P3D_object *params[], int num_params) {
     bp += log.gcount();
   }
 
+  // add data for previous logs
+  if ((tail_bytes_prev > 0) && (log_basenames_prev.size() > 0)) {
+    string log_sep_line = "\n";
+    for (int c=0; c<log_sep_line_chars; ++c) {
+        log_sep_line += log_sep_line_char;
+    }
+    log_sep_line += "\n";
+    for (int i=0; i<(int)log_basenames_prev.size(); ++i) {
+      ifstream log_prev((log_directory+log_basenames_prev[i]).c_str(), ios::in);
+      if (log_prev) {
+        // Insert file separator
+        string log_sep = "\n"+log_sep_line+log_basenames_prev[i]+log_sep_line+"\n";
+        assert(log_sep.length() <= (unsigned)log_sep_bytes); 
+        memcpy(bp, log_sep.data(), log_sep.length());
+        bp += log_sep.length();
+        // Insert prev file data
+        log_prev.seekg(0, ios::end);
+        size_t file_size = (size_t)log_prev.tellg();
+        size_t data_size = tail_bytes_prev;
+        if (data_size > file_size) {
+          data_size = file_size;
+        }
+        log_prev.seekg(file_size - data_size, ios::beg);
+        log_prev.read(bp, data_size);
+        bp += log_prev.gcount();
+      }
+    }
+  }
+
   assert(bp <= buffer + return_size);
 
   P3D_object *result = new P3DStringObject(buffer, bp - buffer);
   delete[] buffer;
-
+  
   return result;
 }
 

+ 44 - 0
direct/src/plugin/p3dSession.cxx

@@ -29,6 +29,7 @@
 #include "run_p3dpython.h"
 
 #include <ctype.h>
+#include <time.h>
 
 #ifndef _WIN32
 #include <fcntl.h>
@@ -1019,6 +1020,49 @@ start_p3dpython(P3DInstance *inst) {
   }
 #endif  // _WIN32
 
+  // Check if we want to keep copies of recent logs on disk.
+  // Get the log history count from the HTML tokens, or from the
+  // p3d_info.xml file.
+  int log_history = inst->get_fparams().lookup_token_int("log_history");
+  if (!log_basename.empty() && (log_history > 1)) {
+    // Append suffix separator
+    log_basename += "-";
+
+    // Delete all but the most recent 'log_history' logs
+    vector<string> all_logs;
+    vector<string> matching_logs;
+    string log_directory = inst_mgr->get_log_directory();
+    inst_mgr->scan_directory(log_directory, all_logs);
+    for (int i=0; i<(int)all_logs.size(); ++i) {
+      if ((all_logs[i].size() > 4) &&
+          (all_logs[i].find(log_basename) == 0) &&
+          (all_logs[i].substr(all_logs[i].size() - 4) == string(".log"))) {
+        matching_logs.push_back((log_directory + all_logs[i]));
+      }
+    }
+    for (int i=0; i<(int)matching_logs.size()-log_history; ++i) {
+      unlink(matching_logs[i].c_str());
+    }
+
+    // Append a timestamp suffix to the log_basename
+    _tzset();
+    time_t log_time_seconds = time(NULL);
+    struct tm *log_time_local_p = localtime(&log_time_seconds);
+    if (log_time_local_p != NULL) {
+      struct tm log_time_local = *log_time_local_p;
+      static const size_t buffer_size = 16;
+      char buffer[buffer_size];
+      sprintf(buffer, "%02d%02d%02d_%02d%02d%02d", 
+              (int)(log_time_local.tm_year+1900-2000),
+              (int)(log_time_local.tm_mon),
+              (int)(log_time_local.tm_mday),
+              (int)(log_time_local.tm_hour),
+              (int)(log_time_local.tm_min),
+              (int)(log_time_local.tm_sec));
+      log_basename += buffer;
+    }
+  }
+
   if (!console_output && !log_basename.empty()) {
     _log_pathname = inst_mgr->get_log_directory();
     _log_pathname += log_basename;

+ 4 - 1
direct/src/plugin/p3d_plugin.h

@@ -120,7 +120,10 @@ extern "C" {
    written.  Otherwise, the compiled-in default is used; if there is
    no compiled-in default, no logfile output will be generated by the
    core API.  Note that the individual instances also have their own
-   log_basename values.
+   log_basename values.  If log_history is greater than zero, the
+   most recent log_history (count) logs generated (per log_basename)
+   will be retained on disk, each named uniquely by appending a 
+   timestamp to the log_basename before file creation.
 
    Next, trusted_environment should be set true to indicate that the
    environment and p3d file are already trusted.  If this is set, the