Branch data Line data Source code
1 : : /* 2 : : ** Copyright (C) 2020 CERN 3 : : ** 4 : : ** This software is provided 'as-is', without any express or implied 5 : : ** warranty. In no event will the authors be held liable for any damages 6 : : ** arising from the use of this software. 7 : : ** 8 : : ** Permission is granted to anyone to use this software for any purpose, 9 : : ** including commercial applications, and to alter it and redistribute it 10 : : ** freely, subject to the following restrictions: 11 : : ** 12 : : ** 1. The origin of this software must not be misrepresented; you must not 13 : : ** claim that you wrote the original software. If you use this software 14 : : ** in a product, an acknowledgment in the product documentation would be 15 : : ** appreciated but is not required. 16 : : ** 2. Altered source versions must be plainly marked as such, and must not be 17 : : ** misrepresented as being the original software. 18 : : ** 3. This notice may not be removed or altered from any source distribution. 19 : : ** 20 : : ** Created on: 2020-09-01T14:31:16+02:00 21 : : ** Author: Sylvain Fargier <sfargier> <sylvain.fargier@cern.ch> 22 : : ** 23 : : */ 24 : : 25 : : #include "Flock.hpp" 26 : : 27 : : #include <vector> 28 : : 29 : : #include <errno.h> 30 : : #include <fcntl.h> 31 : : #include <stdio.h> 32 : : #include <string.h> 33 : : #include <sys/file.h> 34 : : #include <unistd.h> 35 : : 36 : : #include "Exception.hpp" 37 : : 38 : : using namespace ccut; 39 : : 40 : : const std::string Flock::DefaultLock = "/run/lock/puppetlock"; 41 : : 42 : : #define UNLOCKED 0 43 : : #define LOCKED 1 44 : : #define LOCKING 2 45 : : 46 : 5 : Flock::Flock(Flock::Mode mode, const std::string &file) : 47 : 5 : m_mode(mode), 48 : 5 : m_fileName(file), 49 : 5 : m_locked(false) 50 : : { 51 : 5 : m_fd = ::open(m_fileName.c_str(), O_RDONLY | O_CREAT, 0644); 52 : 5 : if (m_fd < 0) 53 : 1 : throw make_errno_exception(); 54 : 5 : } 55 : : 56 : 8 : Flock::~Flock() 57 : : { 58 : 4 : unlock(); 59 : 4 : close(m_fd); 60 : 4 : } 61 : : 62 : 4 : void Flock::lock() 63 : : { 64 : 4 : int expected = UNLOCKED; 65 : 8 : if (m_locked.compare_exchange_strong(expected, LOCKED)) 66 : : { 67 : 3 : if (flock(m_fd, (m_mode == Exclusive) ? LOCK_EX : LOCK_SH) != 0) 68 : : { 69 : 0 : m_locked.store(UNLOCKED); 70 : 0 : throw make_errno_exception(); 71 : : } 72 : : } 73 : 4 : } 74 : : 75 : 7 : bool Flock::try_lock() 76 : : { 77 : 7 : int expected = UNLOCKED; 78 : 14 : if (m_locked.compare_exchange_strong(expected, LOCKING)) 79 : : { 80 : 6 : if (flock(m_fd, 81 : 12 : ((m_mode == Exclusive) ? LOCK_EX : LOCK_SH) | LOCK_NB) != 0) 82 : : { 83 : 2 : if (errno == EWOULDBLOCK) 84 : : { 85 : 2 : m_locked.store(UNLOCKED); 86 : 2 : return false; 87 : : } 88 : : else 89 : : { 90 : 0 : m_locked.store(UNLOCKED); 91 : 0 : throw make_errno_exception(); 92 : : } 93 : : } 94 : 4 : m_locked.store(LOCKED); 95 : : } 96 : 10 : return m_locked.load() == LOCKED; 97 : : } 98 : : 99 : 8 : void Flock::unlock() 100 : : { 101 : 16 : if (m_locked.exchange(UNLOCKED) == LOCKED) 102 : : { 103 : 7 : flock(m_fd, LOCK_UN); 104 : : } 105 : 8 : }