diff options
Diffstat (limited to 'src/MTS_IO_LockFile.cpp')
-rw-r--r-- | src/MTS_IO_LockFile.cpp | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/src/MTS_IO_LockFile.cpp b/src/MTS_IO_LockFile.cpp new file mode 100644 index 0000000..c013699 --- /dev/null +++ b/src/MTS_IO_LockFile.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2015 by Multi-Tech Systems + * + * This file is part of libmts_io. + * + * libmts_io is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * libmts_io 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with libmts_io. If not, see <http://www.gnu.org/licenses/>. + * + */ + +/*! + \file MTS_IO_LockFile.cpp + \brief A brief description + \date Oct 8, 2014 + \author sgodinez + + A more elaborate description +*/ + +#include <mts/MTS_IO_LockFile.h> +#include <mts/MTS_Timer.h> +#include <mts/MTS_Logger.h> +#include <mts/MTS_System.h> +#include <mts/MTS_Text.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> + +using namespace MTS::IO; + +LockFile::LockFile(const std::string& sFile) +: m_sFile(sFile) +, m_iLockFd(-1) +{ + +} + +LockFile::~LockFile() { + unlock(); +} + +bool LockFile::lock(uint32_t attemptMillis) { + if(isLocked()) { + return true; + } + + MTS::Timer timer; + + timer.start(); + while(timer.getMillis() < attemptMillis) { + m_iLockFd =::open(m_sFile.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0644); + if (m_iLockFd < 0) { + // device already locked -> bail out + printWarning("LockFile| Failed to Lock [%s] [%d][%s]", m_sFile.c_str(), errno, strerror(errno)); + + //Check if lock file's process still exists + std::string sResult; + if(MTS::System::readFile(m_sFile, sResult) == 0 && sResult.size() > 0) { + struct stat sts; + std::string sProc = "/proc/" + MTS::Text::trim(sResult); + if (stat(sProc.c_str(), &sts) == -1 && errno == ENOENT) { + printWarning("LockFile| Current Lock's Process [%s] does not exist. Removing lock.", sResult.c_str()); + // process doesn't exist -> remove file + ::unlink(m_sFile.c_str()); + } + } + + } else { + //TODO: Investigate using flock in addition to minicom-style lock : flock(m_iLockFd, LOCK_EX | LOCK_NB); + + // %4d to make concurrent mgetty (if any) happy. + // Mgetty treats 4-bytes lock files as binary, + // not text, PID. Making 5+ char file. Brrr... + char buf[256] = {0}; + sprintf(buf, "%4d\n", getpid()); + write(m_iLockFd, buf, strlen(buf)); + close(m_iLockFd); + return true; + } + uint32_t randomSleepTime = ((rand() % 10) + 1) * 100000; //Sleep from 100ms to 1 Second + ::usleep(randomSleepTime); + } + return false; +} + +void LockFile::unlock() { + if(isLocked()) { + ::unlink(m_sFile.c_str()); + //TODO: flock cleanup : flock(m_iLockFd, LOCK_UN); + m_iLockFd = -1; + } +} + +bool LockFile::isLocked() { + return m_iLockFd >= 0; +} + |