Kea  1.9.9-git
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 
27 namespace isc {
28 namespace log {
29 namespace 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 
40 bool
41 InterprocessSyncFile::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 
88 bool
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 
102 bool
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 
116 bool
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
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)
#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-dhcp-ddns.
const std::string task_name_
The task name.
int fd_