This snapshot, if up-to-date, may be used to accellerate loading of projects with very long histories.tags/non-daw-v1.1.0
| @@ -25,6 +25,8 @@ | |||
| #include <stdarg.h> | |||
| #include <string.h> | |||
| #include "util/file.h" | |||
| #include <algorithm> | |||
| 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(); | |||
| @@ -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 ) | |||
| { | |||
| @@ -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)) | |||
| @@ -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 <sys/stat.h> | |||
| #include <sys/types.h> | |||
| #include <unistd.h> | |||
| 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 ); | |||
| } | |||
| @@ -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 ); | |||