implement log_history functionality

This commit is contained in:
Ken Patel 2010-01-16 01:31:03 +00:00
parent d18f226684
commit 8dc84e42d8
3 changed files with 130 additions and 3 deletions

View File

@ -450,9 +450,11 @@ call_read_log(P3D_object *params[], int num_params) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
P3D_object *P3DMainObject:: P3D_object *P3DMainObject::
read_log(const string &log_pathname, P3D_object *params[], int num_params) { 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); ifstream log(log_pathname.c_str(), ios::in);
if (!log) { if (!log) {
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
return inst_mgr->new_undefined_object(); 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); 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. // Get the size of the file.
log.seekg(0, ios::end); log.seekg(0, ios::end);
size_t file_size = (size_t)log.tellg(); 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; 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"; nout << "allocating " << return_size << " bytes to return.\n";
char *buffer = new char[return_size]; char *buffer = new char[return_size];
if (buffer == NULL) { if (buffer == NULL) {
@ -524,11 +575,40 @@ read_log(const string &log_pathname, P3D_object *params[], int num_params) {
bp += log.gcount(); 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); assert(bp <= buffer + return_size);
P3D_object *result = new P3DStringObject(buffer, bp - buffer); P3D_object *result = new P3DStringObject(buffer, bp - buffer);
delete[] buffer; delete[] buffer;
return result; return result;
} }

View File

@ -29,6 +29,7 @@
#include "run_p3dpython.h" #include "run_p3dpython.h"
#include <ctype.h> #include <ctype.h>
#include <time.h>
#ifndef _WIN32 #ifndef _WIN32
#include <fcntl.h> #include <fcntl.h>
@ -1019,6 +1020,49 @@ start_p3dpython(P3DInstance *inst) {
} }
#endif // _WIN32 #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()) { if (!console_output && !log_basename.empty()) {
_log_pathname = inst_mgr->get_log_directory(); _log_pathname = inst_mgr->get_log_directory();
_log_pathname += log_basename; _log_pathname += log_basename;

View File

@ -120,7 +120,10 @@ extern "C" {
written. Otherwise, the compiled-in default is used; if there is written. Otherwise, the compiled-in default is used; if there is
no compiled-in default, no logfile output will be generated by the no compiled-in default, no logfile output will be generated by the
core API. Note that the individual instances also have their own 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 Next, trusted_environment should be set true to indicate that the
environment and p3d file are already trusted. If this is set, the environment and p3d file are already trusted. If this is set, the