using inter-process lock
In Linux
A tutorial on how to use flock
http://www.ecst.csuchico.edu/~beej/guide/ipc/flock.html
Linux command: ipcs and ipcrm ACE
In ACE
ACE_OS::flock_xxx is a wrapper facility on top of flock which is fully supported in Linux 2.4.
In windows 2003 server, it is not working well. Instead, we can use ACE_Process_Mutex
Note:
Essentially, the initialization of a lock is to open a file. In order to avoid file handler leaking, we need to call flock_destroy() or delete the ACE_Process_Mutex object.
If we fail to get the lock by trywrlock(), we call flock_destroy() to release the file handler created in flock_init(), but we have to use “0” to indicate that we do not want to unlink the file; else it will break the lock if other processes depends on this file.
In Linux, the process_mutex is implemented by semaphore. Semaphore is a system wide resource. It will lead to serious situation if there is a leak on it. You can use ipcs or ipcrm to dump and control semaphore.
While flock will be released once the process is gone, therefore, it is much safer in case the process could be possibly killed abnormally.
Here is the code snippet.
#if !defined(WIN32) //in Linux
void SymLoggerControl::finiLog()
{
ACE_OS::flock_destroy(&m_flock);
}
int SymLoggerControl::initAutoIndex(const SymString &filename, const SymString &i_name)
{
const int MAX_TRY = 1000;
int iret = -1;
if (i_name != "sim")
return iret;
SymString fstr;
SymString lockName;
for (int i=1; i<MAX_TRY;i++)
{
fstr = filename + "." + intToString(i) + ".log";
lockName = "."+i_name + intToString(fstr.hash());
if (ACE_OS::flock_init(&m_flock,O_CREAT|O_RDWR,lockName.c_str(),0600)!=0)
continue;
if (ACE_OS::flock_trywrlock(&m_flock)!=0)
{
//we use 0 to indicate that the destroy can not unlink the file
//else it breaks the lock on other processes
ACE_OS::flock_destroy(&m_flock,0);
continue;
}
setAutoIndex(i);
return iret;
}
setAutoIndex(0);
return -1;
}
#else
void SymLoggerControl::finiLog()
{
if (m_logfileLock)
m_logfileLock->release();
}
int SymLoggerControl::initAutoIndex(const SymString &filename, const SymString &i_name)
{
if (i_name != "sim")
return 0;
const int MAX_TRY = 1000;
SymString lockName;
SymString fstr;
for (int i=1; i< MAX_TRY;i++)
{
fstr = filename + "." + intToString(i) + ".log";
lockName = i_name + intToString(fstr.hash());
// try to get the lock.
ACE_NEW_RETURN(m_logfileLock, ACE_Process_Mutex(lockName.c_str()), -1);
if (m_logfileLock->tryacquire() != 0)
{
//avoid memory leak
SAFE_DELETE(m_logfileLock);
continue;
}
setAutoIndex(i);
return 0;
}
setAutoIndex(0);
return -1;
}