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.
This commit is contained in:
parent
c3603a8bfd
commit
f093abb887
|
@ -25,6 +25,8 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "util/file.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
using std::min;
|
using std::min;
|
||||||
using std::max;
|
using std::max;
|
||||||
|
@ -49,34 +51,57 @@ Loggable::open ( const char *filename )
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
|
Loggable::_fp = NULL;
|
||||||
|
|
||||||
if ( ! ( fp = fopen( filename, "a+" ) ) )
|
if ( ! ( fp = fopen( filename, "a+" ) ) )
|
||||||
{
|
{
|
||||||
WARNING( "Could not open log file for writing!" );
|
WARNING( "Could not open log file for writing!" );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* replay log */
|
if ( newer( "snapshot", filename ) )
|
||||||
{
|
{
|
||||||
/* FIXME: bogus */
|
DMESSAGE( "Loading snapshot" );
|
||||||
char buf[BUFSIZ];
|
|
||||||
|
|
||||||
while ( fscanf( fp, "%[^\n]\n", buf ) == 1 )
|
FILE *fp = fopen( "snapshot", "r" );
|
||||||
{
|
|
||||||
if ( ! ( ! strcmp( buf, "{" ) || ! strcmp( buf, "}" ) ) )
|
replay( fp );
|
||||||
{
|
|
||||||
if ( *buf == '\t' )
|
fclose( fp );
|
||||||
do_this( buf + 1, false );
|
|
||||||
else
|
|
||||||
do_this( buf, false );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DMESSAGE( "Replaying journal" );
|
||||||
|
|
||||||
|
replay( fp );
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek( fp, 0, SEEK_END );
|
||||||
|
|
||||||
Loggable::_fp = fp;
|
Loggable::_fp = fp;
|
||||||
|
|
||||||
return true;
|
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 */
|
/** close journal and delete all loggable objects, returing the systemt to a blank slate */
|
||||||
bool
|
bool
|
||||||
Loggable::close ( void )
|
Loggable::close ( void )
|
||||||
|
@ -91,6 +116,8 @@ Loggable::close ( void )
|
||||||
|
|
||||||
_fp = NULL;
|
_fp = NULL;
|
||||||
|
|
||||||
|
snapshot( "snapshot" );
|
||||||
|
|
||||||
for ( int i = 0; i < _log_id - 1; ++i )
|
for ( int i = 0; i < _log_id - 1; ++i )
|
||||||
{
|
{
|
||||||
Loggable ** l = &_loggables[ i ];
|
Loggable ** l = &_loggables[ i ];
|
||||||
|
@ -333,10 +360,11 @@ Loggable::undo ( void )
|
||||||
delete[] buf;
|
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
|
/** write a snapshot of the state of all loggable objects, sufficient
|
||||||
* for later reconstruction, to /fp/ */
|
* for later reconstruction, to /fp/ */
|
||||||
bool
|
bool
|
||||||
Loggable::snapshot( FILE *fp )
|
Loggable::snapshot ( FILE *fp )
|
||||||
{
|
{
|
||||||
FILE *ofp = _fp;
|
FILE *ofp = _fp;
|
||||||
|
|
||||||
|
@ -380,6 +408,19 @@ Loggable::snapshot( FILE *fp )
|
||||||
return true;
|
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 */
|
/** Replace the journal with a snapshot of the current state */
|
||||||
void
|
void
|
||||||
Loggable::compact ( void )
|
Loggable::compact ( void )
|
||||||
|
@ -396,6 +437,9 @@ Loggable::compact ( void )
|
||||||
void
|
void
|
||||||
Loggable::log ( const char *fmt, ... )
|
Loggable::log ( const char *fmt, ... )
|
||||||
{
|
{
|
||||||
|
if ( ! _fp )
|
||||||
|
return;
|
||||||
|
|
||||||
/* FIXME: bogus limit */
|
/* FIXME: bogus limit */
|
||||||
static char buf[1024];
|
static char buf[1024];
|
||||||
static int i = 0;
|
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 );
|
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
|
void
|
||||||
Loggable::log_create ( void ) const
|
Loggable::log_create ( void ) const
|
||||||
{
|
{
|
||||||
|
if ( ! _fp )
|
||||||
|
/* replaying, don't bother */
|
||||||
|
|
||||||
|
return;
|
||||||
log( "%s 0x%X create ", class_name(), _id );
|
log( "%s 0x%X create ", class_name(), _id );
|
||||||
|
|
||||||
Log_Entry e;
|
Log_Entry e;
|
||||||
|
|
||||||
get( e );
|
get( e );
|
||||||
|
|
||||||
log_print( NULL, &e );
|
if ( e.size() )
|
||||||
|
log_print( NULL, &e );
|
||||||
|
else
|
||||||
|
log( "\n" );
|
||||||
|
|
||||||
if ( Loggable::_level == 0 )
|
if ( Loggable::_level == 0 )
|
||||||
Loggable::flush();
|
Loggable::flush();
|
||||||
|
|
|
@ -104,16 +104,10 @@ private:
|
||||||
static void log ( const char *fmt, ... );
|
static void log ( const char *fmt, ... );
|
||||||
|
|
||||||
static void flush ( void );
|
static void flush ( void );
|
||||||
static
|
|
||||||
void indent ( void )
|
|
||||||
{
|
|
||||||
int n = Loggable::_level;
|
|
||||||
|
|
||||||
while ( n-- )
|
|
||||||
log( "\t" );
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool snapshot( FILE * fp );
|
static bool snapshot( FILE * fp );
|
||||||
|
static bool snapshot( const char *name );
|
||||||
|
static bool replay ( FILE *fp );
|
||||||
|
|
||||||
void init ( bool loggable=true )
|
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 := $(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:=$(Timeline_SRCS:.fl=.C)
|
||||||
Timeline_SRCS:=$(sort $(Timeline_SRCS))
|
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 );
|
Loading…
Reference in New Issue