Allow the user to open a file if the lock wasn't obtained

after going through a dialog.


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@2962 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Dave Peticolas 2000-09-27 20:34:07 +00:00
parent 7842e38587
commit ce05f4893d
3 changed files with 271 additions and 193 deletions

View File

@ -37,78 +37,86 @@
#include "file-history.h" #include "file-history.h"
/* This static indicates the debugging module that this .o belongs to. */ /* This static indicates the debugging module that this .o belongs to. */
// static short module = MOD_GUI; /* static short module = MOD_GUI; */
/** GLOBALS *********************************************************/ /** GLOBALS *********************************************************/
static Session *current_session = NULL; static Session *current_session = NULL;
static AccountGroup *topgroup = NULL; /* the current top of the hierarchy */ static AccountGroup *topgroup = NULL; /* the current top of the hierarchy */
/********************************************************************\
* fileMenubarCB -- handles file menubar choices *
\********************************************************************/
#define SHOW_IO_ERR_MSG(io_error) { \ /* ======================================================== */
switch (io_error) { \
case ERR_FILEIO_NO_ERROR: \ static gboolean
break; \ show_file_error (int io_error, char *newfile)
case ERR_FILEIO_FILE_NOT_FOUND: \ {
sprintf (buf, FILE_NOT_FOUND_MSG, newfile); \ gboolean uh_oh = FALSE;
gnc_error_dialog (buf); \ char *buf = NULL;
uh_oh = 1; \
break; \ switch (io_error)
case ERR_FILEIO_FILE_EMPTY: \ {
sprintf (buf, FILE_EMPTY_MSG, newfile); \ case ERR_FILEIO_NO_ERROR:
gnc_error_dialog (buf); \ break;
uh_oh = 1; \ case ERR_FILEIO_FILE_NOT_FOUND:
break; \ buf = g_strdup_printf (FILE_NOT_FOUND_MSG, newfile);
case ERR_FILEIO_FILE_TOO_NEW: \ gnc_error_dialog (buf);
gnc_error_dialog ( FILE_TOO_NEW_MSG); \ uh_oh = TRUE;
uh_oh = 1; \ break;
break; \ case ERR_FILEIO_FILE_EMPTY:
case ERR_FILEIO_FILE_TOO_OLD: \ buf = g_strdup_printf (FILE_EMPTY_MSG, newfile);
if (!gnc_verify_dialog( FILE_TOO_OLD_MSG, TRUE )) { \ gnc_error_dialog (buf);
xaccFreeAccountGroup (newgrp); \ uh_oh = TRUE;
newgrp = NULL; \ break;
uh_oh = 1; \ case ERR_FILEIO_FILE_TOO_NEW:
} \ gnc_error_dialog (FILE_TOO_NEW_MSG);
break; \ uh_oh = TRUE;
case ERR_FILEIO_FILE_BAD_READ: \ break;
if (!gnc_verify_dialog( FILE_BAD_READ_MSG, TRUE )) { \ case ERR_FILEIO_FILE_TOO_OLD:
xaccFreeAccountGroup (newgrp); \ if (!gnc_verify_dialog (FILE_TOO_OLD_MSG, TRUE))
newgrp = NULL; \ uh_oh = TRUE;
uh_oh = 1; \ break;
} \ case ERR_FILEIO_FILE_BAD_READ:
break; \ if (!gnc_verify_dialog (FILE_BAD_READ_MSG, TRUE))
default: \ uh_oh = TRUE;
break; \ break;
} \ default:
break;
}
g_free (buf);
return uh_oh;
} }
/* ======================================================== */
#define SHOW_LOCK_ERR_MSG(session) \ static gboolean
{ \ show_session_error(Session *session, char *newfile)
int norr = xaccSessionGetError (session); \ {
if (ETXTBSY == norr) \ int norr = xaccSessionGetError (session);
{ \ gboolean uh_oh = FALSE;
sprintf (buf, FMB_LOCKED_MSG, newfile); \ char *buf = NULL;
gnc_error_dialog (buf); \
uh_oh = 1; \ if (ETXTBSY == norr)
} \ {
else \ uh_oh = TRUE;
if (ERANGE == norr) \ }
{ \ else if (ERANGE == norr)
sprintf (buf, FILE_NOT_FOUND_MSG, newfile); \ {
gnc_error_dialog (buf); \ buf = g_strdup_printf (FILE_NOT_FOUND_MSG, newfile);
uh_oh = 1; \ gnc_error_dialog (buf);
} \ uh_oh = TRUE;
else \ }
if (norr) \ else if (norr)
{ \ {
sprintf (buf, FMB_INVALID_MSG, newfile); \ buf = (FMB_INVALID_MSG, newfile);
gnc_error_dialog (buf); \ gnc_error_dialog (buf);
uh_oh = 1; \ uh_oh = TRUE;
} \ }
} \
g_free(buf);
return uh_oh;
}
/* ======================================================== */ /* ======================================================== */
@ -191,6 +199,29 @@ gncFileQuerySave (void)
return TRUE; return TRUE;
} }
/* ======================================================== */
static gboolean
gncLockFailHandler (const char *file)
{
const char *format = _("Gnucash could not obtain the lock for\n"
" %s.\n"
"That file may be in use by another user,\n"
"in which case you should not open the file.\n"
"\nDo you want to proceed with opening the file?");
char *message;
gboolean result;
if (file == NULL)
return FALSE;
message = g_strdup_printf (format, file);
result = gnc_verify_dialog (message, FALSE);
g_free (message);
return result;
}
/* ======================================================== */ /* ======================================================== */
/* private utilities for file open; done in two stages */ /* private utilities for file open; done in two stages */
@ -199,16 +230,17 @@ gncPostFileOpen (const char * filename)
{ {
Session *newsess; Session *newsess;
AccountGroup *oldgrp; AccountGroup *oldgrp;
int io_error, uh_oh=0; gboolean uh_oh = FALSE;
char buf[BUFSIZE]; int io_error;
AccountGroup *newgrp; AccountGroup *newgrp;
char * newfile; char * newfile;
if (!filename) return; if (!filename) return;
newfile = xaccResolveFilePath (filename); newfile = xaccResolveFilePath (filename);
if (!newfile) { if (!newfile) {
sprintf (buf, FILE_NOT_FOUND_MSG, filename); char *buf = g_strdup_printf (FILE_NOT_FOUND_MSG, filename);
gnc_error_dialog (buf); gnc_error_dialog (buf);
g_free(buf);
return; return;
} }
@ -227,26 +259,32 @@ gncPostFileOpen (const char * filename)
* switchover is not something we want to keep in a journal. */ * switchover is not something we want to keep in a journal. */
gnc_set_busy_cursor(NULL); gnc_set_busy_cursor(NULL);
xaccLogDisable(); xaccLogDisable();
newgrp = xaccSessionBeginFile (newsess, newfile); newgrp = xaccSessionBeginFile (newsess, newfile, gncLockFailHandler);
xaccLogEnable(); xaccLogEnable();
gnc_unset_busy_cursor(NULL); gnc_unset_busy_cursor(NULL);
/* check for session errors, put up appropriate dialog */ /* check for session errors, put up appropriate dialog */
SHOW_LOCK_ERR_MSG (newsess); uh_oh = show_session_error (newsess, newfile);
if (!uh_oh) if (!uh_oh)
{ {
/* check for i/o error, put up appropriate error message */ /* check for i/o error, put up appropriate error message */
io_error = xaccGetFileIOError(); io_error = xaccGetFileIOError();
SHOW_IO_ERR_MSG(io_error); uh_oh = show_file_error (io_error, newfile);
if (uh_oh)
{
xaccFreeAccountGroup (newgrp);
newgrp = NULL;
}
/* Umm, came up empty-handed, i.e. the file was not found. */ /* Umm, came up empty-handed, i.e. the file was not found. */
/* This is almost certainly not what the user wanted. */ /* This is almost certainly not what the user wanted. */
if (!uh_oh && !newgrp && !io_error) if (!uh_oh && !newgrp && !io_error)
{ {
sprintf (buf, FILE_NOT_FOUND_MSG, newfile); char *buf = g_strdup_printf (FILE_NOT_FOUND_MSG, newfile);
gnc_error_dialog ( buf); gnc_error_dialog (buf);
uh_oh = 1; g_free (buf);
uh_oh = TRUE;
} }
} }
@ -258,9 +296,9 @@ gncPostFileOpen (const char * filename)
/* well, no matter what, I think its a good idea to have /* well, no matter what, I think its a good idea to have
* a topgroup around. For example, early in the gnucash startup * a topgroup around. For example, early in the gnucash startup
* sequence, the user opens a file ... if this open fails for any * sequence, the user opens a file; if this open fails for any
* reason, we don't want to leave them high & dry without a topgroup, * reason, we don't want to leave them high & dry without a topgroup,
* because if user continues, then bad things will happen ... * because if the user continues, then bad things will happen.
*/ */
if (NULL == topgroup) if (NULL == topgroup)
{ {
@ -343,7 +381,6 @@ gncFileSave (void)
{ {
AccountGroup *newgrp = NULL; AccountGroup *newgrp = NULL;
char * newfile; char * newfile;
char buf[BUFSIZE];
int io_error, norr, uh_oh = 0; int io_error, norr, uh_oh = 0;
/* hack alert -- Somehow make sure all in-progress edits get committed! */ /* hack alert -- Somehow make sure all in-progress edits get committed! */
@ -392,7 +429,13 @@ gncFileSave (void)
io_error = xaccGetFileIOError(); io_error = xaccGetFileIOError();
newfile = xaccSessionGetFilePath(current_session); newfile = xaccSessionGetFilePath(current_session);
gnc_history_add_file(newfile); gnc_history_add_file(newfile);
SHOW_IO_ERR_MSG(io_error);
uh_oh = show_file_error (io_error, newfile);
if (uh_oh)
{
xaccFreeAccountGroup (newgrp);
newgrp = NULL;
}
/* going down -- abandon ship */ /* going down -- abandon ship */
if (uh_oh) return; if (uh_oh) return;
@ -411,8 +454,8 @@ gncFileSaveAs (void)
char *newfile; char *newfile;
AccountGroup *newgrp; AccountGroup *newgrp;
char * oldfile; char * oldfile;
char buf[BUFSIZE]; int io_error;
int io_error, uh_oh = 0; gboolean uh_oh = FALSE;
filename = fileBox(SAVE_STR, "*.gnc"); filename = fileBox(SAVE_STR, "*.gnc");
if (!filename) return; if (!filename) return;
@ -424,8 +467,9 @@ gncFileSaveAs (void)
*/ */
newfile = xaccResolveFilePath (filename); newfile = xaccResolveFilePath (filename);
if (!newfile) { if (!newfile) {
sprintf (buf, FILE_NOT_FOUND_MSG, filename); char *buf = g_strdup_printf (FILE_NOT_FOUND_MSG, filename);
gnc_error_dialog (buf); gnc_error_dialog (buf);
g_free (buf);
return; return;
} }
oldfile = xaccSessionGetFilePath (current_session); oldfile = xaccSessionGetFilePath (current_session);
@ -449,17 +493,22 @@ gncFileSaveAs (void)
* edit; the mass deletetion of accounts and transactions during * edit; the mass deletetion of accounts and transactions during
* switchover is not something we want to keep in a journal. */ * switchover is not something we want to keep in a journal. */
xaccLogDisable(); xaccLogDisable();
newgrp = xaccSessionBeginFile (newsess, newfile); newgrp = xaccSessionBeginFile (newsess, newfile, gncLockFailHandler);
xaccLogEnable(); xaccLogEnable();
/* check for session errors (e.g. file locked by another user) */ /* check for session errors (e.g. file locked by another user) */
SHOW_LOCK_ERR_MSG (newsess); uh_oh = show_session_error (newsess, newfile);
if (!uh_oh) if (!uh_oh)
{ {
/* check for i/o error, put up appropriate error message */ /* check for i/o error, put up appropriate error message */
io_error = xaccGetFileIOError(); io_error = xaccGetFileIOError();
SHOW_IO_ERR_MSG(io_error); uh_oh = show_file_error (io_error, newfile);
if (uh_oh)
{
xaccFreeAccountGroup (newgrp);
newgrp = NULL;
}
} }
/* going down -- abandon ship */ /* going down -- abandon ship */
@ -496,10 +545,15 @@ gncFileSaveAs (void)
if (newgrp) if (newgrp)
{ {
char *tmpmsg; char *tmpmsg;
tmpmsg = alloca (strlen (FMB_EEXIST_MSG) + strlen (newfile)); gboolean result;
sprintf (tmpmsg, FMB_EEXIST_MSG, newfile);
tmpmsg = g_strdup_printf (FMB_EEXIST_MSG, newfile);
result = gnc_verify_dialog (tmpmsg, FALSE);
g_free (tmpmsg);
/* if user says cancel, we should break out */ /* if user says cancel, we should break out */
if (! gnc_verify_dialog (tmpmsg, FALSE)) return; if (!result)
return;
/* Whoa-ok. Blow away the previous file. /* Whoa-ok. Blow away the previous file.
* Do not disable logging ... we want to capture the * Do not disable logging ... we want to capture the
@ -537,7 +591,6 @@ gncFileQuit (void)
xaccSessionEnd (current_session); xaccSessionEnd (current_session);
xaccSessionDestroy (current_session); xaccSessionDestroy (current_session);
current_session = NULL; current_session = NULL;
// xaccGroupWindowDestroy (grp);
xaccFreeAccountGroup (grp); xaccFreeAccountGroup (grp);
topgroup = NULL; topgroup = NULL;
} }

View File

@ -1,15 +1,3 @@
/*
* FILE:
* Session.c
*
* FUNCTION:
* Provide wrappers for initiating/concluding a file-editing session.
*
* HISTORY:
* Created by Linas Vepstas December 1998
* Copyright (c) 1998-2000 Linas Vepstas
*/
/********************************************************************\ /********************************************************************\
* This program is free software; you can redistribute it and/or * * This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as * * modify it under the terms of the GNU General Public License as *
@ -29,6 +17,18 @@
* Boston, MA 02111-1307, USA gnu@gnu.org * * Boston, MA 02111-1307, USA gnu@gnu.org *
\********************************************************************/ \********************************************************************/
/*
* FILE:
* Session.c
*
* FUNCTION:
* Provide wrappers for initiating/concluding a file-editing session.
*
* HISTORY:
* Created by Linas Vepstas December 1998
* Copyright (c) 1998-2000 Linas Vepstas
*/
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <limits.h> #include <limits.h>
@ -81,7 +81,7 @@ Session *
xaccMallocSession (void) xaccMallocSession (void)
{ {
Session *sess; Session *sess;
sess = (Session *) malloc (sizeof (Session)); sess = g_new(Session, 1);
xaccInitSession (sess); xaccInitSession (sess);
return sess; return sess;
@ -179,7 +179,7 @@ xaccSessionBegin (Session *sess, const char * sid)
} }
/* add 5 to space past 'file:' */ /* add 5 to space past 'file:' */
retval = xaccSessionBeginFile (sess, sid+5); retval = xaccSessionBeginFile (sess, sid+5, NULL);
return retval; return retval;
} }
@ -217,14 +217,81 @@ extern Backend * pgendNew (void);
/* ============================================================== */ /* ============================================================== */
AccountGroup * static gboolean
xaccSessionBeginFile (Session *sess, const char * filefrag) xaccSessionGetFileLock (Session *sess)
{ {
struct stat statbuf; struct stat statbuf;
char pathbuf[PATH_MAX]; char pathbuf[PATH_MAX];
char *path = NULL; char *path = NULL;
int rc; int rc;
rc = stat (sess->lockfile, &statbuf);
if (!rc) {
/* oops .. file is all locked up .. */
sess->errtype = ETXTBSY;
return FALSE;
}
sess->lockfd = open (sess->lockfile, O_RDWR | O_CREAT | O_EXCL , 0);
if (0 > sess->lockfd) {
/* oops .. file is all locked up .. */
sess->errtype = ETXTBSY;
return FALSE;
}
/* OK, now work around some NFS atomic lock race condition
* mumbo-jumbo. We do this by linking a unique file, and
* then examing the link count. At least that's what the
* NFS programmers guide suggests.
* Note: the "unique filename" must be unique for the
* triplet filename-host-process, otherwise accidental
* aliases can occur.
*/
/* apparently, even this code may not work for some NFS
* implementations. In the long run, I am told that
* ftp.debian.org
* /pub/debian/dists/unstable/main/source/libs/liblockfile_0.1-6.tar.gz
* provides a better long-term solution.
*/
strcpy (pathbuf, sess->lockfile);
path = strrchr (pathbuf, '.');
sprintf (path, ".%lx.%d.LNK", gethostid(), getpid());
link (sess->lockfile, pathbuf);
rc = stat (sess->lockfile, &statbuf);
if (rc) {
/* oops .. stat failed! This can't happen! */
sess->errtype = ETXTBSY;
unlink (pathbuf);
close (sess->lockfd);
unlink (sess->lockfile);
return FALSE;
}
if (2 != statbuf.st_nlink) {
/* oops .. stat failed! This can't happen! */
sess->errtype = ETXTBSY;
unlink (pathbuf);
close (sess->lockfd);
unlink (sess->lockfile);
return FALSE;
}
sess->linkfile = g_strdup (pathbuf);
return TRUE;
}
/* ============================================================== */
AccountGroup *
xaccSessionBeginFile (Session *sess, const char * filefrag,
SessionLockFailHandler handler)
{
struct stat statbuf;
int rc;
if (!sess) return NULL; if (!sess) return NULL;
/* clear the error condition of previous errors */ /* clear the error condition of previous errors */
@ -252,87 +319,27 @@ xaccSessionBeginFile (Session *sess, const char * filefrag)
} }
/* Store the sessionid URL also ... */ /* Store the sessionid URL also ... */
strcpy (pathbuf, "file:"); sess->sessionid = g_strconcat ("file:", filefrag, NULL);
strcat (pathbuf, filefrag);
sess->sessionid = strdup (pathbuf);
/* ---------------------------------------------------- */ /* ---------------------------------------------------- */
/* We should now have a fully resolved path name. /* We should now have a fully resolved path name.
* Lets see if we can get a lock on it. * Lets see if we can get a lock on it. */
*/
sess->lockfile = malloc (strlen (sess->fullpath) + 5); sess->lockfile = g_strconcat(sess->fullpath, ".LCK", NULL);
strcpy (sess->lockfile, sess->fullpath);
strcat (sess->lockfile, ".LCK");
rc = stat (sess->lockfile, &statbuf); if (!xaccSessionGetFileLock (sess)) {
if (!rc) { if (!handler || !handler (sess->fullpath)) {
/* oops .. file is all locked up .. */ g_free (sess->sessionid); sess->sessionid = NULL;
sess->errtype = ETXTBSY; g_free (sess->fullpath); sess->fullpath = NULL;
free (sess->sessionid); sess->sessionid = NULL; g_free (sess->lockfile); sess->lockfile = NULL;
free (sess->fullpath); sess->fullpath = NULL;
free (sess->lockfile); sess->lockfile = NULL;
return NULL; return NULL;
} }
sess->lockfd = open (sess->lockfile, O_RDWR | O_CREAT | O_EXCL , 0);
if (0 > sess->lockfd) {
/* oops .. file is all locked up .. */
sess->errtype = ETXTBSY;
free (sess->sessionid); sess->sessionid = NULL;
free (sess->fullpath); sess->fullpath = NULL;
free (sess->lockfile); sess->lockfile = NULL;
return NULL;
} }
/* OK, now work around some NFS atomic lock race condition
* mumbo-jumbo. We do this by linking a unique file, and
* then examing the link count. At least that's what the
* NFS programmers guide suggests.
* Note: the "unique filename" must be unique for the
* triplet filename-host-process, otherwise accidental
* aliases can occur.
*/
/* appearently, even this code may not work for some NFS
* implementations. In the long run, I am told that
* ftp.debian.org
* /pub/debian/dists/unstable/main/source/libs/liblockfile_0.1-6.tar.gz
* provides a better long-term solution.
*/
strcpy (pathbuf, sess->lockfile);
path = strrchr (pathbuf, '.');
sprintf (path, ".%lx.%d.LNK", gethostid(), getpid());
link (sess->lockfile, pathbuf);
rc = stat (sess->lockfile, &statbuf);
if (rc) {
/* oops .. stat failed! This can't happen! */
sess->errtype = ETXTBSY;
unlink (pathbuf);
close (sess->lockfd);
unlink (sess->lockfile);
free (sess->sessionid); sess->sessionid = NULL;
free (sess->fullpath); sess->fullpath = NULL;
free (sess->lockfile); sess->lockfile = NULL;
return NULL;
}
if (2 != statbuf.st_nlink) {
/* oops .. stat failed! This can't happen! */
sess->errtype = ETXTBSY;
unlink (pathbuf);
close (sess->lockfd);
unlink (sess->lockfile);
free (sess->sessionid); sess->sessionid = NULL;
free (sess->fullpath); sess->fullpath = NULL;
free (sess->lockfile); sess->lockfile = NULL;
return NULL;
}
sess->linkfile = strdup (pathbuf);
/* ---------------------------------------------------- */ /* ---------------------------------------------------- */
/* OK, if we've gotten this far, then we've succesfully obtained /* OK, if we've gotten this far, then we've succesfully obtained
* an atomic lock on the file. Go read the file contents ... * an atomic lock on the file. Go read the file contents if it
* well, read it only if it exists ... * exists. */
*/
sess->errtype = 0; sess->errtype = 0;
sess->topgroup = NULL; sess->topgroup = NULL;
@ -387,13 +394,20 @@ xaccSessionEnd (Session *sess)
if (sess->linkfile) unlink (sess->linkfile); if (sess->linkfile) unlink (sess->linkfile);
if (0 < sess->lockfd) close (sess->lockfd); if (0 < sess->lockfd) close (sess->lockfd);
if (sess->lockfile) unlink (sess->lockfile); if (sess->lockfile) unlink (sess->lockfile);
if (sess->sessionid) free (sess->sessionid); sess->sessionid = NULL;
if (sess->fullpath) free (sess->fullpath); sess->fullpath = NULL;
if (sess->lockfile) free (sess->lockfile); sess->lockfile = NULL;
if (sess->linkfile) free (sess->linkfile); sess->linkfile = NULL;
sess->topgroup = NULL;
return; g_free (sess->sessionid);
sess->sessionid = NULL;
g_free (sess->fullpath);
sess->fullpath = NULL;
g_free (sess->lockfile);
sess->lockfile = NULL;
g_free (sess->linkfile);
sess->linkfile = NULL;
sess->topgroup = NULL;
} }
void void
@ -401,7 +415,7 @@ xaccSessionDestroy (Session *sess)
{ {
if (!sess) return; if (!sess) return;
xaccSessionEnd (sess); xaccSessionEnd (sess);
free (sess); g_free (sess);
} }
@ -415,29 +429,32 @@ MakeHomeDir (void)
{ {
int rc; int rc;
struct stat statbuf; struct stat statbuf;
char *home, *path; char *home;
char *path;
char *data;
/* Punt. Can't figure out where home is. */ /* Punt. Can't figure out where home is. */
home = getenv ("HOME"); home = getenv ("HOME");
if (!home) return; if (!home) return;
path = alloca (strlen (home) +50); path = g_strconcat(home, "/.gnucash", NULL);
strcpy (path, home);
strcat (path, "/.gnucash");
rc = stat (path, &statbuf); rc = stat (path, &statbuf);
if (rc) { if (rc) {
/* assume that the stat failed only because the dir is absent, /* assume that the stat failed only because the dir is absent,
* and not because its read-protected or other error. * and not because its read-protected or other error.
* Go ahead and make it. Don't bother much with checking mkdir * Go ahead and make it. Don't bother much with checking mkdir
* for errors; seems pointless ... */ * for errors; seems pointless. */
mkdir (path, S_IRWXU); /* perms = S_IRWXU = 0700 */ mkdir (path, S_IRWXU); /* perms = S_IRWXU = 0700 */
} }
strcat (path, "/data"); data = g_strconcat (path, "/data");
rc = stat (path, &statbuf); rc = stat (data, &statbuf);
if (rc) if (rc)
mkdir (path, S_IRWXU); mkdir (data, S_IRWXU);
g_free (path);
g_free (data);
} }
/* ============================================================== */ /* ============================================================== */

View File

@ -88,7 +88,12 @@ void xaccSessionDestroy (Session *);
* *
* The xaccSessionBeginFile() routine is identical to the xaccSessionBegin() * The xaccSessionBeginFile() routine is identical to the xaccSessionBegin()
* routine, except that the argument is a filename (i.e. the five * routine, except that the argument is a filename (i.e. the five
* letters "file:" should not be prepended). * letters "file:" should not be prepended) and there is an additional
* function argument. This function is called if xaccSessionBeginFile
* fails to obtain a lock for the file. If it returns true, the file
* is loaded anyway. If it returns false, or the handler is NULL, a
* failed lock attempt will abort the load. The lock fail handler is
* passed the filename of the data file being loaded.
* *
* The xaccSessionGetFilePath() routine returns the fully-qualified file * The xaccSessionGetFilePath() routine returns the fully-qualified file
* path for the session. That is, if a relative or partial filename * path for the session. That is, if a relative or partial filename
@ -168,8 +173,11 @@ void xaccSessionDestroy (Session *);
* xaccSessionDestroy (sess); * xaccSessionDestroy (sess);
* */ * */
typedef gboolean (*SessionLockFailHandler)(const char *file);
AccountGroup * xaccSessionBegin (Session *, const char * sessionid); AccountGroup * xaccSessionBegin (Session *, const char * sessionid);
AccountGroup * xaccSessionBeginFile (Session *, const char * filename); AccountGroup * xaccSessionBeginFile (Session *, const char * filename,
SessionLockFailHandler handler);
int xaccSessionGetError (Session *); int xaccSessionGetError (Session *);
AccountGroup * xaccSessionGetGroup (Session *); AccountGroup * xaccSessionGetGroup (Session *);
void xaccSessionSetGroup (Session *, AccountGroup *topgroup); void xaccSessionSetGroup (Session *, AccountGroup *topgroup);