Hi Ivav,
> > Since Coda does not have any support for file locking, the problem is
> > understandable. It is not really big problem because I still be able to
> > use GnuCash on Coda. Just ignore the message.
> >
> > > http://www.gnucash.org/docs/C/gnucash-guide/backup1.html
>
> If I interpret the documentation right, the locking GnuCash uses is
> file creation in exclusive mode.
>
> Though such operaton is not guaranteed to be exclusive on Coda,
> normally it will not fail, so GnuCash should be happy (and clean the
> "lock files" afterwards).
> Looking at the source or strace results would possibly give the answer,
> why you seem to observe that problem on Coda but not otherwise.
I did not means to be too offensive, but I did check in the GnuCash and does
not assume it is only CODA problem. I have download GnuCash and
take a look at the code. The section of GnuCash code that does locking is
attached at the end. I agree with Ivan that GnuCash uses exclusive mode.
I plans to do something with it, but before doing so I need to what do you
guys think about the problem it self. Since CODA does not have support for
file locking, which I refer to Jan, work around for CODA is needed. If any
one have any idea, please let me know. I wll get back later.
Is it possible to implement locking mechanism in CODA? I am a newbie to CODA
code "hacking" :-P ...
>
> My 2c,
> --
> Ivan
Thanks,
Anocha
========================================================
Code from $GNUCASH_SRC_DIR/src/backend/file/gnc-backend-file.c
------------------------------------------------------------------------------------
static gboolean
gnc_file_be_get_file_lock (FileBackend *be)
{
struct stat statbuf;
char pathbuf[PATH_MAX];
char *path = NULL;
int rc;
rc = stat (be->lockfile, &statbuf);
if (!rc)
{
/* oops .. file is all locked up .. */
xaccBackendSetError ((Backend*)be, ERR_BACKEND_LOCKED);
return FALSE;
}
be->lockfd = open (be->lockfile, O_RDWR | O_CREAT | O_EXCL , 0);
if (be->lockfd < 0)
{
/* oops .. file is all locked up .. */
xaccBackendSetError ((Backend*)be, ERR_BACKEND_LOCKED);
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, be->lockfile);
path = strrchr (pathbuf, '.');
sprintf (path, ".%lx.%d.LNK", gethostid(), getpid());
rc = link (be->lockfile, pathbuf);
if (rc)
{
static gboolean
gnc_file_be_get_file_lock (FileBackend *be)
{
struct stat statbuf;
char pathbuf[PATH_MAX];
char *path = NULL;
int rc;
rc = stat (be->lockfile, &statbuf);
if (!rc)
{
/* oops .. file is all locked up .. */
xaccBackendSetError ((Backend*)be, ERR_BACKEND_LOCKED);
return FALSE;
}
be->lockfd = open (be->lockfile, O_RDWR | O_CREAT | O_EXCL , 0);
if (be->lockfd < 0)
{
/* oops .. file is all locked up .. */
xaccBackendSetError ((Backend*)be, ERR_BACKEND_LOCKED);
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, be->lockfile);
path = strrchr (pathbuf, '.');
sprintf (path, ".%lx.%d.LNK", gethostid(), getpid());
rc = link (be->lockfile, pathbuf);
if (rc)
{
/* If hard links aren't supported, just allow the lock. */
if (errno == EOPNOTSUPP || errno == EPERM)
{
be->linkfile = NULL;
return TRUE;
}
/* Otherwise, something else is wrong. */
xaccBackendSetError ((Backend*)be, ERR_BACKEND_LOCKED);
unlink (pathbuf);
close (be->lockfd);
unlink (be->lockfile);
return FALSE;
}
rc = stat (be->lockfile, &statbuf);
if (rc)
{
/* oops .. stat failed! This can't happen! */
xaccBackendSetError ((Backend*)be, ERR_BACKEND_LOCKED);
unlink (pathbuf);
close (be->lockfd);
unlink (be->lockfile);
return FALSE;
}
if (statbuf.st_nlink != 2)
{
xaccBackendSetError ((Backend*)be, ERR_BACKEND_LOCKED);
unlink (pathbuf);
close (be->lockfd);
unlink (be->lockfile);
return FALSE;
}
be->linkfile = g_strdup (pathbuf);
return TRUE;
}
========================================================