This is the second version of the backup proposal. It's quite
a bit different than the first. Thanks to everyone who commented
on the first one, both on the list and in private.
Proposed Backup Strategy for GnuCash v2
=======================================
Goals
-----
GnuCash's method for backing up its database files should protect
against three kinds of failures:
1. A crash during the operation of GnuCash that doesn't affect the
database file, but which prevents newly-entered data from being
saved.
2. An error during the writing of a GnuCash database file that
prevents the file being written correctly, resulting in an obviously
incorrect file. This could be caused by, e.g., a power or hardware
failure, running out of disk space, the user hitting ctrl-c or killing
the process in some other way, or a bug in the GnuCash file i/o code.
3. The creation of a GnuCash database file that is a readable but
incorrect in a non-obvious way. Such a problem may not be discovered
for some time. Such a problem could be caused by a bug in GnuCash or
by the user accidentally entering wrong data or performing an operation
that was later determined to be undesirable (like deleting an account).
Current Status
--------------
GnuCash only writes the main database file when requested by the user.
Currently, when saving, GnuCash writes the main database file and then
writes a time-stamped duplicate of that file. Thus, the user will have
a 'save history' of database files that record the state of the database
at each point the user requested a save. This 'save history' will
protect against failure #3, as you can revert to an earlier, correct
version of the database.
GnuCash also creates an ascii log file which records changes made to
GnuCash entities during operation. Currently, this log file can be
used to manually recover from failure #1, but there is no automated
way to do so, or any other support for protecting against this kind
of error.
Problems
--------
+ Recovering manually from a log is tedious and thus failure #1 is a
real pain.
+ None of the current backup methods will protect against failure #2.
+ Creating a 'save history' will generate lots of large files, especially
for users who save a lot (like me).
Proposed Solution
-----------------
+ To better handle failure #1, GnuCash should be able to automatically
recover from log files.
As changes are made to the database, they will be logged to the
filename "<original name>.log", where <original name> is the name
of the database file.
When GnuCash starts, it should check for the presence of the log file
and, if it exists and has a later modification time than the main
file, GnuCash should prompt the user to load the log file in addition
to the main file (since the log file will have the changes to the
main file that occurred after the last save).
+ To handle failure #2, GnuCash should change the way it saves the main
database file. Saving should be done by:
1. Writing the new database to the temporary file.
The temporary file name will be "<original name>.tmp"
2. Moving or copying the old database to a backup file,
overwriting any existing backup file. The backup file
name will be "<original name>~"
3. Moving the temporary file to the main database file.
Thus, after successful completion of a save, the original database will
be saved in a backup file.
If there is a writing failure during step 1, the original database is
untouched.
+ GnuCash should maintain log histories, rather than save histories, to
handle failure #3.
After saving, the current log file should be renamed to be the first
log history file, and a new log file should be started.
Log history files should be named as "<original name>.log.I" where I
is an integer and means the log history file is the Ith file in the
history.
Thus, loading the database <original name> should be equivalent to
loading (in order) <original name>.log.1 ... <original name>.log.N
where N is the number of log history files.
Example
=======
The files in the directory where the main database name 'gnucash.gnc'
is located will be as follows:
gnucash.gnc - main database file
gnucash.gnc~ - backup file from last save
gnucash.gnc.tmp - temporary file created during save
This file will only existing during
saving, unless there is an i/o error.
gnucash.gnc.log - The current log file. This file will
only exist while gnucash.gnc is open,
unless there is an i/o error.
gnucash.gnc.log.1 - These are the log history files.
gnucash.gnc.log.2
...
gnucash.gnc.log.N
Pseudo-Code Implementation
--------------------------
Saving: /* Save to temporary file */
save_database_to_file("<original name>.tmp");
if (error) {
report_error_to_gui();
return;
}
/* Make backup file */
rename("<original name>", "<original name>~");
if (error) {
report_error_to_gui();
/* At this point, the current database file was
* written, but there was an error creating the
* backup file. Should we ask the user whether
* to proceed with overwriting the original, or
* should we just tell them where the temporary
* file was written and return? */
return;
}
/* Move temporary onto original */
rename("<original name>.tmp", "<original name>");
if (error) {
report_error_to_gui();
/* We should tell the user that the current database
* was saved to the temporary file, so they know where
* to find it. */
return;
}
I = find_next_log_index();
rename("<original name>.log.I");
if (error)
report_error_to_gui();
start_new_log("<original name>.log");
if (error)
report_error_to_gui();
I would appreciate any comments you have.
thanks,
dave
--
Gnucash Developer's List
To unsubscribe send empty email to: [EMAIL PROTECTED]