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::
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;
}

View File

@ -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;

View File

@ -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