wow. that was easy: git mv core nucleus
[feisty_meow.git] / core / library / loggers / file_logger.cpp
diff --git a/core/library/loggers/file_logger.cpp b/core/library/loggers/file_logger.cpp
deleted file mode 100644 (file)
index a18caa1..0000000
+++ /dev/null
@@ -1,375 +0,0 @@
-/*****************************************************************************\
-*                                                                             *
-*  Name   : file_logger                                                       *
-*  Author : Chris Koeritz                                                     *
-*                                                                             *
-*******************************************************************************
-* Copyright (c) 2000-$now By Author.  This program is free software; you can  *
-* redistribute it and/or modify it under the terms of the GNU General Public  *
-* License as published by the Free Software Foundation; either version 2 of   *
-* the License or (at your option) any later version.  This is online at:      *
-*     http://www.fsf.org/copyleft/gpl.html                                    *
-* Please send any updates to: fred@gruntose.com                               *
-\*****************************************************************************/
-
-#include "critical_events.h"
-#include "file_logger.h"
-#include "logging_filters.h"
-
-#include <basis/astring.h>
-#include <basis/functions.h>
-#include <basis/mutex.h>
-#include <configuration/application_configuration.h>
-#include <filesystem/byte_filer.h>
-#include <filesystem/directory.h>
-#include <filesystem/filename.h>
-#include <mathematics/chaos.h>
-#include <structures/static_memory_gremlin.h>
-#include <textual/byte_formatter.h>
-
-#ifdef __WIN32__
-  #include <io.h>
-#endif
-#include <stdio.h>
-#ifdef __UNIX__
-  #include <unistd.h>
-#endif
-
-using namespace basis;
-using namespace configuration;
-using namespace filesystem;
-using namespace mathematics;
-using namespace structures;
-using namespace textual;
-
-namespace loggers {
-
-const int REDUCE_FACTOR = 5;
-  // we whack this portion of the file every time we truncate.  if it's set
-  // to 14, for example, then a 14th of the file is whacked every time whacking
-  // is needed.
-
-const int MAXIMUM_BUFFER_SIZE = 140000;
-  // the maximum allowed chunk that can be copied from the old logfile
-  // to the current one.
-
-int static_chaos() {
-  static chaos __hidden_chaos;
-  return __hidden_chaos.inclusive(0, 1280004);
-}
-
-file_logger::file_logger()
-: _filename(new astring()),
-  _file_limit(DEFAULT_LOG_FILE_SIZE),
-  _outfile(NIL),
-  _flock(new mutex)
-{
-  name("");
-}
-
-file_logger::file_logger(const astring &initial_filename, int limit)
-: _filename(new astring()),
-  _file_limit(limit),
-  _outfile(NIL),
-  _flock(new mutex)
-{
-  name(initial_filename); 
-  // we don't open the file right away because we don't know they'll ever
-  // use the thing.
-}
-
-file_logger::~file_logger()
-{
-  close_file();
-  WHACK(_filename);
-  WHACK(_flock);
-}
-
-basis::astring file_logger::log_file_for_app_name()
-{
-  filename prog = application_configuration::application_name();
-  return application_configuration::make_logfile_name(prog.rootname() + ".log");
-}
-
-bool file_logger::reopen()
-{
-  auto_synchronizer l(*_flock);
-  name(*_filename);
-  return open_file();
-}
-
-void file_logger::close_file()
-{
-  auto_synchronizer l(*_flock);
-  if (_outfile) _outfile->flush();
-    // dump anything that hasn't gone out yet.
-  WHACK(_outfile);
-}
-
-void file_logger::name(const astring &new_name)
-{
-  auto_synchronizer l(*_flock);
-  close_file();
-  *_filename = new_name; 
-}
-
-int file_logger::size_reduction() const
-{
-  auto_synchronizer l(*_flock);
-  return int(_file_limit / REDUCE_FACTOR);
-}
-
-bool file_logger::good() const
-{
-  auto_synchronizer l(*_flock);
-  if (!_outfile && !_file_limit) return true;
-  if (!_outfile) return false;
-  return _outfile->good();
-}
-
-astring file_logger::name() const
-{
-  auto_synchronizer l(*_flock);
-  return *_filename;
-}
-
-void file_logger::flush()
-{
-  auto_synchronizer l(*_flock);
-  if (!_outfile) open_file();
-  if (_outfile) _outfile->flush();
-}
-
-bool file_logger::open_file()
-{
-  auto_synchronizer l(*_flock);
-  close_file();  // close any existing log file.
-
-  if (!_file_limit) {
-    // if there's a limit of zero, we'll never open the file.
-    return true;
-  }
-
-  // make sure we've got a name.
-  if (!*_filename) {
-    // if the name is empty, they don't want to save to a normal log file.
-    _outfile = new byte_filer;
-    return true;
-  }
-
-  // canonicalize the name so that we use the same tag for synchronization.
-  // this might still fail if there are some jokers using different relative
-  // paths to the file.  but if it's an absolute name, it should work.
-  for (int i = 0; i < _filename->length(); i++)
-    if ((*_filename)[i] == '\\') (*_filename)[i] = '/';
-
-  // make sure the directory containing the log file exists, if we can.
-  filename temp_file(*_filename);
-  filename temp_dir(temp_file.dirname());
-  if (!temp_dir.good() || !temp_dir.is_directory()) {
-    directory::recursive_create(temp_dir);
-  }
-
-  // if this opening doesn't work, then we just can't log.
-  _outfile = new byte_filer(*_filename, "a+b");
-  return _outfile->good();
-}
-
-outcome file_logger::log(const base_string &to_show, int filter)
-{
-  if (!_file_limit) return common::OKAY;
-
-  size_t current_size = 0;
-  {
-    auto_synchronizer l(*_flock);
-    if (!member(filter)) return common::OKAY;
-    if (!_outfile) open_file();
-    if (!_outfile) return common::BAD_INPUT;  // file opening failed.
-    if (!_outfile->good()) return common::BAD_INPUT;
-      // there is no log file currently.
-  
-    // dump the string out.
-    if (to_show.length())
-      _outfile->write((abyte *)to_show.observe(), to_show.length());
-//hmmm: need eol feature again.
-//    if (eol() != NO_ENDING) {
-//      astring end = get_ending();
-astring end = parser_bits::platform_eol_to_chars();
-      _outfile->write((abyte *)end.s(), end.length());
-//    }
-    current_size = _outfile->tell();
-    flush();
-  }
-
-  // check if we need to truncate yet.
-  if (current_size > _file_limit) truncate(_file_limit - size_reduction());
-  return common::OKAY;
-}
-
-outcome file_logger::log_bytes(const byte_array &to_log, int filter)
-{
-  if (!_file_limit) return common::OKAY;
-
-  size_t current_size = 0;
-  {
-    auto_synchronizer l(*_flock);
-    if (!member(filter)) return common::OKAY;
-    if (!_outfile) open_file();
-    if (!_outfile) return common::BAD_INPUT;  // file opening failed.
-    if (!_outfile->good()) return common::BAD_INPUT;
-      // there is no log file currently.
-  
-    // dump the contents out.
-    if (to_log.length())
-      _outfile->write(to_log.observe(), to_log.length());
-    current_size = _outfile->tell();
-    flush();
-  }
-
-  // check if we need to truncate yet.
-  if (current_size > _file_limit)
-    truncate(_file_limit - size_reduction());
-  return common::OKAY;
-}
-
-outcome file_logger::format_bytes(const byte_array &to_log, int filter)
-{
-  if (!_file_limit) return common::OKAY;
-
-  {
-    auto_synchronizer l(*_flock);
-    if (!member(filter)) return common::OKAY;
-    if (!_outfile) open_file();
-    if (!_outfile) return common::BAD_INPUT;  // file opening failed.
-    if (!_outfile->good()) return common::BAD_INPUT;
-      // there is no log file currently.
-  }
-
-  // dump the contents out.
-  if (to_log.length()) {
-    astring dumped_form;
-    byte_formatter::text_dump(dumped_form, to_log);
-    log(dumped_form);
-  }
-
-  // check if we need to truncate yet.
-//  int current_size = _outfile->tell();
-//  flush();
-//  if (current_size > _file_limit) truncate(_file_limit - size_reduction());
-
-  return common::OKAY;
-}
-
-//hmmm: should move the truncation functionality into a function on
-//      the file object.
-
-void file_logger::truncate(size_t new_size)
-{
-  auto_synchronizer l(*_flock);
-  if (!_outfile) open_file();
-  if (!_outfile) return;  // file opening failed.
-  if (!_outfile->good()) return;
-    // there is no log file currently.
-
-  size_t current_size = 0;
-
-///  // our synchronization scheme allows us to use this inter-application
-///  // lock; the logger's own lock is always acquired first.  no one else can
-///  // grab the "file_lock", so no deadlocks.
-///
-///  rendezvous file_lock(*_filename + "_trunclock");
-///  if (!file_lock.healthy()) {
-///    critical_events::write_to_critical_events((astring("could not create "
-///       "lock for ") + *_filename).s());
-///    return;
-///  }
-///  // waiting forever until the file lock succeeds.  as long as there are
-///  // no deadlocks permitted, then this shouldn't be too dangerous...
-///  bool got_lock = file_lock.lock(rendezvous::ENDLESS_WAIT);
-///  if (!got_lock) {
-///    critical_events::write_to_critical_events((astring("could not acquire "
-///        "lock for ") + *_filename).s());
-///    return;
-///  }
-
-  // make sure we weren't second in line to clean the file.  if someone else
-  // already did this, we don't need to do it again.
-  _outfile->seek(0, byte_filer::FROM_END);
-  current_size = _outfile->tell();
-  if (current_size <= new_size) {
-    // release the lock and leave since we don't need to change the file.
-///    file_lock.unlock();
-    return;
-  }
-  // create a bogus temporary name.
-  astring new_file(astring::SPRINTF, "%s.tmp.%d", name().s(),
-      static_chaos());
-
-  // unlink the temp file, if it exists.
-  unlink(new_file.s());
-
-  // grab the current size before we close our file.
-  current_size = _outfile->tell();
-
-  // redo the main stream for reading also.
-  WHACK(_outfile);
-  _outfile = new byte_filer(*_filename, "rb");
-
-  // open the temp file as blank for writing.
-  byte_filer *hold_stream = new byte_filer(new_file, "w+b");
-
-  int start_of_keep = int(current_size - new_size);
-
-  // position the old file where it will be about the right size.
-  _outfile->seek(start_of_keep, byte_filer::FROM_START);
-
-  astring buff(' ', MAXIMUM_BUFFER_SIZE + 1);
-
-  // we only read as long as the file end isn't hit and we're not past the
-  // original end of the file.  if the file got bigger during the truncation,
-  // that's definitely not our doing and should not be coddled.  we've seen
-  // a situation where we never thought we'd hit the end of the file yet before
-  // adding this size check.
-  size_t bytes_written = 0;  // how many bytes have gone out already.
-//hmmm: loop could be extracted to some kind of dump from file one into file
-//      two operation that starts at a particular address and has a particular
-//      size or range.
-  while (!_outfile->eof() && (bytes_written <= new_size)) {
-    // grab a line from the input file.
-    buff[0] = '\0';  // set it to be an empty string.
-    int bytes_read = _outfile->read((abyte *)buff.s(), MAXIMUM_BUFFER_SIZE);
-    if (!bytes_read)
-      break;
-    bytes_written += bytes_read;
-    // write the line and a CR to the output file.
-    if (!_outfile->eof() || bytes_read)
-      hold_stream->write((abyte *)buff.s(), bytes_read);
-  }
-  WHACK(_outfile);
-  _outfile = new byte_filer(*_filename, "w+b");
-
-  // we think the new stream is ready for writing.
-  size_t hold_size = hold_stream->tell();
-    // get the current length of the clipped chunk.
-  bytes_written = 0;  // reset our counter.
-
-  // jump back to the beginning of the temp file.
-  hold_stream->seek(0, byte_filer::FROM_START);
-  while (!hold_stream->eof() && (bytes_written <= hold_size) ) {
-    // scoot all the old data back into our file.
-    int bytes_read = hold_stream->read((abyte *)buff.s(), MAXIMUM_BUFFER_SIZE);
-    if (!bytes_read)
-      break;
-        // something funky happened; we shouldn't be at the end of the file yet.
-    bytes_written += bytes_read;
-    if (!hold_stream->eof() || bytes_read)
-      _outfile->write((abyte *)buff.s(), bytes_read);
-  }
-  WHACK(hold_stream);
-  unlink(new_file.s());  // trash the temp file.
-///  file_lock.unlock();  // repeal the process-wide lock.
-  name(*_filename);  // re-open the regular file with append semantics.
-}
-
-} //namespace.
-