libdap Updated for version 3.21.1
libdap4 is an implementation of OPeNDAP's DAP protocol.
mp_lock_guard.h
Go to the documentation of this file.
1
2// Copyright (c) 2023 OPeNDAP, Inc.
3// Author: James Gallagher <jgallagher@opendap.org>
4//
5// This library is free software; you can redistribute it and/or
6// modify it under the terms of the GNU Lesser General Public
7// License as published by the Free Software Foundation; either
8// version 2.1 of the License, or (at your option) any later version.
9//
10// This library is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13// Lesser General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public
16// License along with this library; if not, write to the Free Software
17// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18//
19// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
20
21#ifndef LIBDAP4_MP_LOCK_GUARD_H
22#define LIBDAP4_MP_LOCK_GUARD_H
23
24#include <exception>
25#include <iostream>
26#include <string>
27
28#include <cerrno>
29#include <fcntl.h>
30#include <sys/stat.h>
31#include <unistd.h>
32
33namespace libdap {
34
35static inline std::string get_errno() {
36 const char *s_err = strerror(errno);
37 return s_err ? s_err : "unknown error";
38}
39
46public:
48 virtual ~mp_lock_guard_logger() = default;
49
50 virtual void log(const std::string &msg) const = 0;
51
52 virtual void error(const std::string &msg) const = 0;
53};
54
61public:
63 ~mp_lock_guard_logger_default() override = default;
64
65 void log(const std::string &msg) const override { std::cerr << "~mp_lock_guard: " << msg << std::endl; }
66
67 void error(const std::string &msg) const override { throw std::runtime_error("mp_lock_guard: " + msg); }
68};
69
80public:
81 enum class operation { read, write };
82
83private:
84 int d_fd = -1;
85 bool d_locked = false;
86 bool d_released = false; // Use this so instances can go out of scope without releasing the lock.
87 operation d_op;
88 const mp_lock_guard_logger &d_logger;
89
90 void m_get_lock() {
91 if (d_op == operation::write) {
92 struct flock lock {};
93 lock.l_type = F_WRLCK;
94 lock.l_whence = SEEK_SET;
95 lock.l_start = 0;
96 lock.l_len = 0;
97 lock.l_pid = getpid();
98 if (fcntl(d_fd, F_SETLKW, &lock) == -1) {
99 d_logger.error("Could not write lock the cache-control file: " + get_errno());
100 }
101 } else {
102 struct flock lock {};
103 lock.l_type = F_RDLCK;
104 lock.l_whence = SEEK_SET;
105 lock.l_start = 0;
106 lock.l_len = 0;
107 lock.l_pid = getpid();
108 if (fcntl(d_fd, F_SETLKW, &lock) == -1) {
109 d_logger.error("Could not read lock the cache-control file: " + get_errno());
110 }
111 }
112 d_locked = true;
113 }
114
115 friend class mp_lock_guard_test;
116
117public:
118 mp_lock_guard() = delete;
119
120 mp_lock_guard(const mp_lock_guard &) = delete;
121
123
131 : d_fd(fd), d_op(op), d_logger(logger) {
132 m_get_lock();
133 }
134
143 if (!d_released && d_locked) {
144 struct flock lock {};
145 lock.l_type = F_UNLCK;
146 lock.l_whence = SEEK_SET;
147 lock.l_start = 0;
148 lock.l_len = 0;
149 lock.l_pid = getpid();
150 if (fcntl(d_fd, F_SETLK, &lock) == -1) {
151 d_logger.log("Could not unlock the cache-control file: " + get_errno());
152 }
153 }
154 }
155
160 void release() { d_released = true; }
161
165 static void unlock(int fd, const mp_lock_guard_logger &logger = mp_lock_guard_logger_default()) {
166 struct flock lock {};
167 lock.l_type = F_UNLCK;
168 lock.l_whence = SEEK_SET;
169 lock.l_start = 0;
170 lock.l_len = 0;
171 lock.l_pid = getpid();
172 if (fcntl(fd, F_SETLK, &lock) == -1) {
173 logger.error("Could not unlock the cache-control file: " + get_errno());
174 }
175 }
176};
177
178} // namespace libdap
179
180#endif // LIBDAP4_MP_LOCK_GUARD_H
Default logger for mp_lock_guard For this implementation of mp_lock_guard_logger, the log() method wr...
void log(const std::string &msg) const override
void error(const std::string &msg) const override
~mp_lock_guard_logger_default() override=default
Interface for the logger used by mp_lock_guard The idea behind this abstract class (aka,...
virtual void log(const std::string &msg) const =0
virtual void error(const std::string &msg) const =0
virtual ~mp_lock_guard_logger()=default
friend class mp_lock_guard_test
static void unlock(int fd, const mp_lock_guard_logger &logger=mp_lock_guard_logger_default())
mp_lock_guard & operator=(const mp_lock_guard &)=delete
mp_lock_guard(const mp_lock_guard &)=delete
mp_lock_guard(int fd, operation op, const mp_lock_guard_logger &logger=mp_lock_guard_logger_default())
Lock the cache for reading or writing. These are blocking locks.
~mp_lock_guard()
Unlock the cache. Works for both read and write locks.
top level DAP object to house generic methods
Definition AISConnect.cc:30