/*
mylockfile.* - c++ wrapper for file locks (for easy unlocking due to destructors, and abstraction from lowlevel)
Copyright (C) 1999-2003 Matthew Mueller <donut AT dakotacom.net>
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; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _MYLOCKFILE_H_
#define _MYLOCKFILE_H_
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string>
#include <errno.h>
#include "log.h"
//liblockfile doesn't support anything but exclusive locks, so these are only "wants"
#define WANT_SH_LOCK 1
#define WANT_EX_LOCK 0
#define FLOCK_DEBUG_LEV DEBUG_MED
#ifdef HAVE_LIBLOCKFILE
#include <lockfile.h>
class c_lockfile{
public:
string file;
c_lockfile(string filename,int flag){
file=filename;
file.append(".lock");
PDEBUG(FLOCK_DEBUG_LEV,"attempting to lock %s",file.c_str());
int ret=lockfile_create(file.c_str(),10,0);
if (ret){
file = "";
throw ApplicationExFatal(Ex_INIT,"lockfile_create %s: %i (%s)",filename.c_str(),ret,strerror(errno));
}
PDEBUG(FLOCK_DEBUG_LEV,"locked %s",file.c_str());
}
~c_lockfile(){
if (!file.empty()) {
lockfile_remove(file.c_str());
PDEBUG(FLOCK_DEBUG_LEV,"unlocked %s",file.c_str());
}
}
};
#elif HAVE_FLOCK
#include <unistd.h>
#include <sys/file.h>
class c_lockfile{
public:
int fd;
c_lockfile(string filename,int flag){
PDEBUG(FLOCK_DEBUG_LEV,"attempting to flock %s",filename.c_str());
fd=open(filename.c_str(),O_RDONLY);
if (fd<0){
if (errno==ENOENT){
// if (flag&WANT_SH_LOCK)
return;
} else
throw ApplicationExFatal(Ex_INIT,"c_lockfile: open %s (%s)",filename.c_str(),strerror(errno));
}
int ret=flock(fd,(flag&WANT_SH_LOCK)?LOCK_SH:LOCK_EX);
if (ret) {
int savederrno = errno;
close(fd); fd = -1;
throw ApplicationExFatal(Ex_INIT,"c_lockfile: flock %s: %i (%s)",filename.c_str(),ret,strerror(savederrno));
}
PDEBUG(FLOCK_DEBUG_LEV,"flocked %s (%i)",filename.c_str(),fd);
// sleep(10);
}
~c_lockfile(){
if (fd>=0) {
flock(fd,LOCK_UN);
close(fd);
PDEBUG(FLOCK_DEBUG_LEV,"unflocked %i",fd);
}
}
};
#elif HAVE_LOCKFILE
#define WIN32_LEAN_AND_MEAN
#undef NOMINMAX
#define NOMINMAX 1
#include <windows.h>
class c_lockfile{
public:
HANDLE hFile;
string filename;
c_lockfile(string infilename,int flag): hFile(INVALID_HANDLE_VALUE){
filename = infilename + ".lock";//Windows does not allow removing the locked file, (when we rename the .tmp to the real name), so create a seperate lock file instead.
PDEBUG(FLOCK_DEBUG_LEV,"attempting to LockFile %s",filename.c_str());
//if (!fexists(filename.c_str()))
// return;
//hFile = CreateFile(filename.c_str(),GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
hFile = CreateFile(filename.c_str(), GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile==INVALID_HANDLE_VALUE){
throw ApplicationExFatal(Ex_INIT,"c_lockfile: open %s (%i)",filename.c_str(),GetLastError());
}
int tries=1;
while (!LockFile(hFile,0,0,0xFFFFFFFF,0)) {
if (tries++ >= 10) {
CloseHandle(hFile); hFile = INVALID_HANDLE_VALUE;
throw ApplicationExFatal(Ex_INIT,"c_lockfile: LockFile %s: giving up after %i tries",filename.c_str(), tries);
}
sleep(1);
PDEBUG(FLOCK_DEBUG_LEV,"try %i LockFile %s",tries,filename.c_str());
}
PDEBUG(FLOCK_DEBUG_LEV,"locked %s (%p)",filename.c_str(),hFile);
}
~c_lockfile(){
if (hFile!=INVALID_HANDLE_VALUE) {
UnlockFile(hFile,0,0,0xFFFFFFFF,0);
CloseHandle(hFile);
DeleteFile(filename.c_str());
PDEBUG(FLOCK_DEBUG_LEV,"unlocked %s(%p)",filename.c_str(),hFile);
}
}
};
#else
#warning building without any sort of locking at all
class c_lockfile{
public:
c_lockfile(string filename,int flag){}
~c_lockfile(){}
};
#endif
#endif
syntax highlighted by Code2HTML, v. 0.9.1