Kea 2.6.2
interprocess_sync_file.cc
Go to the documentation of this file.
1// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7// This file requires LOCKFILE_DIR to be defined. It points to the default
8// directory where lockfile will be created.
9
10#include <config.h>
11
13
14#include <string>
15#include <cerrno>
16#include <cstring>
17#include <sstream>
18#include <iostream>
19
20#include <stdlib.h>
21#include <string.h>
22#include <unistd.h>
23#include <fcntl.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26
27namespace isc {
28namespace log {
29namespace interprocess {
30
32 if (fd_ != -1) {
33 // This will also release any applied locks.
34 close(fd_);
35 // The lockfile will continue to exist, and we must not delete
36 // it.
37 }
38}
39
40bool
41InterprocessSyncFile::do_lock(int cmd, short l_type) {
42 // Open lock file only when necessary (i.e., here). This is so that
43 // if a default InterprocessSync object is replaced with another
44 // implementation, it doesn't attempt any opens.
45 if (fd_ == -1) {
46 std::string lockfile_path = LOCKFILE_DIR;
47
48 const char* const env = getenv("KEA_LOCKFILE_DIR");
49 if (env != NULL) {
50 lockfile_path = env;
51 }
52
53 lockfile_path += "/" + task_name_ + "_lockfile";
54
55 // Open the lockfile in the constructor so it doesn't do the access
56 // checks every time a message is logged.
57 const mode_t mode = umask(S_IXUSR | S_IXGRP | S_IXOTH); // 0111
58 fd_ = open(lockfile_path.c_str(), O_CREAT | O_RDWR,
59 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); // 0660
60 umask(mode);
61
62 if (fd_ == -1) {
63 std::stringstream tmp;
64
65 // We failed to create a lockfile. This means that the logging
66 // system is unusable. We need to report the issue using plain
67 // print to stderr.
68 tmp << "Unable to use interprocess sync lockfile ("
69 << std::strerror(errno) << "): " << lockfile_path;
70 std::cerr << tmp.str() << std::endl;
71
72 // And then throw exception as usual.
73 isc_throw(InterprocessSyncFileError, tmp.str());
74 }
75 }
76
77 struct flock lock;
78
79 memset(&lock, 0, sizeof (lock));
80 lock.l_type = l_type;
81 lock.l_whence = SEEK_SET;
82 lock.l_start = 0;
83 lock.l_len = 1;
84
85 return (fcntl(fd_, cmd, &lock) == 0);
86}
87
88bool
90 if (is_locked_) {
91 return (true);
92 }
93
94 if (do_lock(F_SETLKW, F_WRLCK)) {
95 is_locked_ = true;
96 return (true);
97 }
98
99 return (false);
100}
101
102bool
104 if (is_locked_) {
105 return (true);
106 }
107
108 if (do_lock(F_SETLK, F_WRLCK)) {
109 is_locked_ = true;
110 return (true);
111 }
112
113 return (false);
114}
115
116bool
118 if (!is_locked_) {
119 return (true);
120 }
121
122 if (do_lock(F_SETLKW, F_UNLCK)) {
123 is_locked_ = false;
124 return (true);
125 }
126
127 return (false);
128}
129
130} // namespace interprocess
131} // namespace log
132} // namespace isc
then both cases could be regarded as being with the completion being signalled by the posting of the completion event However UDP is the most common case and that would involve extra overhead So the open() returns a status indicating whether the operation completed asynchronously. If it did
bool lock()
Acquire the lock (blocks if something else has acquired a lock on the same task name)
bool tryLock()
Try to acquire a lock (doesn't block)
const std::string task_name_
The task name.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Defines the logger used by the top-level component of kea-lfc.