From f093abb887f7c224766fa35a76bc5205737d109f Mon Sep 17 00:00:00 2001 From: Jonathan Moore Liles Date: Wed, 4 Jun 2008 08:44:53 -0500 Subject: [PATCH] Automatically save a snapshot when close()'ing a project. This snapshot, if up-to-date, may be used to accellerate loading of projects with very long histories. --- Timeline/Loggable.C | 83 ++++++++++++++++++++++++++++++++++--------- Timeline/Loggable.H | 10 ++---- Timeline/makefile.inc | 2 +- util/file.C | 40 +++++++++++++++++++++ util/file.h | 21 +++++++++++ 5 files changed, 131 insertions(+), 25 deletions(-) create mode 100644 util/file.C create mode 100644 util/file.h diff --git a/Timeline/Loggable.C b/Timeline/Loggable.C index 45b3aa4..da5cf31 100644 --- a/Timeline/Loggable.C +++ b/Timeline/Loggable.C @@ -25,6 +25,8 @@ #include #include +#include "util/file.h" + #include using std::min; using std::max; @@ -49,34 +51,57 @@ Loggable::open ( const char *filename ) { FILE *fp; + Loggable::_fp = NULL; + if ( ! ( fp = fopen( filename, "a+" ) ) ) { WARNING( "Could not open log file for writing!" ); return false; } - /* replay log */ + if ( newer( "snapshot", filename ) ) { - /* FIXME: bogus */ - char buf[BUFSIZ]; + DMESSAGE( "Loading snapshot" ); - while ( fscanf( fp, "%[^\n]\n", buf ) == 1 ) - { - if ( ! ( ! strcmp( buf, "{" ) || ! strcmp( buf, "}" ) ) ) - { - if ( *buf == '\t' ) - do_this( buf + 1, false ); - else - do_this( buf, false ); - } - } + FILE *fp = fopen( "snapshot", "r" ); + + replay( fp ); + + fclose( fp ); + } + else + { + DMESSAGE( "Replaying journal" ); + + replay( fp ); } + fseek( fp, 0, SEEK_END ); + Loggable::_fp = fp; return true; } +/** replay journal or snapshot */ +bool +Loggable::replay ( FILE *fp ) +{ + /* FIXME: bogus */ + char buf[BUFSIZ]; + + while ( fscanf( fp, "%[^\n]\n", buf ) == 1 ) + { + if ( ! ( ! strcmp( buf, "{" ) || ! strcmp( buf, "}" ) ) ) + { + if ( *buf == '\t' ) + do_this( buf + 1, false ); + else + do_this( buf, false ); + } + } +} + /** close journal and delete all loggable objects, returing the systemt to a blank slate */ bool Loggable::close ( void ) @@ -91,6 +116,8 @@ Loggable::close ( void ) _fp = NULL; + snapshot( "snapshot" ); + for ( int i = 0; i < _log_id - 1; ++i ) { Loggable ** l = &_loggables[ i ]; @@ -333,10 +360,11 @@ Loggable::undo ( void ) delete[] buf; } +/* FIXME: we need a version of this that is fully const, right? */ /** write a snapshot of the state of all loggable objects, sufficient * for later reconstruction, to /fp/ */ bool -Loggable::snapshot( FILE *fp ) +Loggable::snapshot ( FILE *fp ) { FILE *ofp = _fp; @@ -380,6 +408,19 @@ Loggable::snapshot( FILE *fp ) return true; } +bool +Loggable::snapshot ( const char *name ) +{ + FILE *fp; + + if ( ! ( fp = fopen( name, "w" ) )) + return false; + + snapshot( fp ); + + fclose( fp ); +} + /** Replace the journal with a snapshot of the current state */ void Loggable::compact ( void ) @@ -396,6 +437,9 @@ Loggable::compact ( void ) void Loggable::log ( const char *fmt, ... ) { + if ( ! _fp ) + return; + /* FIXME: bogus limit */ static char buf[1024]; static int i = 0; @@ -490,7 +534,7 @@ Loggable::log_print( const Log_Entry *o, const Log_Entry *n ) const o->get( i, &s, &v ); - log( "%s %s%s", s, o->size() == i + 1 ? "" : " " ); + log( "%s %s%s", s, v, o->size() == i + 1 ? "" : " " ); } } @@ -550,13 +594,20 @@ Loggable::log_end ( void ) void Loggable::log_create ( void ) const { + if ( ! _fp ) + /* replaying, don't bother */ + + return; log( "%s 0x%X create ", class_name(), _id ); Log_Entry e; get( e ); - log_print( NULL, &e ); + if ( e.size() ) + log_print( NULL, &e ); + else + log( "\n" ); if ( Loggable::_level == 0 ) Loggable::flush(); diff --git a/Timeline/Loggable.H b/Timeline/Loggable.H index 117b17f..cecc7ef 100644 --- a/Timeline/Loggable.H +++ b/Timeline/Loggable.H @@ -104,16 +104,10 @@ private: static void log ( const char *fmt, ... ); static void flush ( void ); - static - void indent ( void ) - { - int n = Loggable::_level; - - while ( n-- ) - log( "\t" ); - } static bool snapshot( FILE * fp ); + static bool snapshot( const char *name ); + static bool replay ( FILE *fp ); void init ( bool loggable=true ) { diff --git a/Timeline/makefile.inc b/Timeline/makefile.inc index cab845a..4afa01c 100644 --- a/Timeline/makefile.inc +++ b/Timeline/makefile.inc @@ -4,7 +4,7 @@ Timeline_VERSION := 0.5.0 Timeline_SRCS := $(wildcard Timeline/*.C Timeline/*.fl Timeline/Engine/*.C) -Timeline_SRCS += util/debug.C util/Thread.C +Timeline_SRCS += util/debug.C util/Thread.C util/file.C Timeline_SRCS:=$(Timeline_SRCS:.fl=.C) Timeline_SRCS:=$(sort $(Timeline_SRCS)) diff --git a/util/file.C b/util/file.C new file mode 100644 index 0000000..1247e34 --- /dev/null +++ b/util/file.C @@ -0,0 +1,40 @@ + +/*******************************************************************************/ +/* Copyright (C) 2008 Jonathan Moore Liles */ +/* */ +/* 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 program is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU General Public License along */ +/* with This program; see the file COPYING. If not,write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/*******************************************************************************/ + +#include +#include +#include + +long +mtime ( const char *file ) +{ + struct stat st; + + if ( stat( file, &st ) ) + return 0; + + return st.st_mtime; +} + +/** returns /true/ if /file1/ is newer than /file2/ (or file2 doesn't exist) */ +bool +newer ( const char *file1, const char *file2 ) +{ + return mtime( file1 ) > mtime( file2 ); +} diff --git a/util/file.h b/util/file.h new file mode 100644 index 0000000..2853a21 --- /dev/null +++ b/util/file.h @@ -0,0 +1,21 @@ + +/*******************************************************************************/ +/* Copyright (C) 2008 Jonathan Moore Liles */ +/* */ +/* 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 program is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU General Public License along */ +/* with This program; see the file COPYING. If not,write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/*******************************************************************************/ + +long mtime ( const char *file ); +bool newer ( const char *file1, const char *file2 );