interprocess_sync_file.cc 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <log/interprocess/interprocess_sync_file.h>
  15. #include <string>
  16. #include <cerrno>
  17. #include <cstring>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <unistd.h>
  21. #include <fcntl.h>
  22. #include <sys/types.h>
  23. #include <sys/stat.h>
  24. namespace isc {
  25. namespace log {
  26. namespace interprocess {
  27. InterprocessSyncFile::~InterprocessSyncFile() {
  28. if (fd_ != -1) {
  29. // This will also release any applied locks.
  30. close(fd_);
  31. // The lockfile will continue to exist, and we must not delete
  32. // it.
  33. }
  34. }
  35. bool
  36. InterprocessSyncFile::do_lock(int cmd, short l_type) {
  37. // Open lock file only when necessary (i.e., here). This is so that
  38. // if a default InterprocessSync object is replaced with another
  39. // implementation, it doesn't attempt any opens.
  40. if (fd_ == -1) {
  41. std::string lockfile_path = LOCKFILE_DIR;
  42. const char* const env = getenv("KEA_LOCKFILE_DIR");
  43. if (env != NULL) {
  44. lockfile_path = env;
  45. }
  46. lockfile_path += "/" + task_name_ + "_lockfile";
  47. // Open the lockfile in the constructor so it doesn't do the access
  48. // checks every time a message is logged.
  49. const mode_t mode = umask(0111);
  50. fd_ = open(lockfile_path.c_str(), O_CREAT | O_RDWR, 0660);
  51. umask(mode);
  52. if (fd_ == -1) {
  53. isc_throw(InterprocessSyncFileError,
  54. "Unable to use interprocess sync lockfile ("
  55. << std::strerror(errno) << "): " << lockfile_path);
  56. }
  57. }
  58. struct flock lock;
  59. memset(&lock, 0, sizeof (lock));
  60. lock.l_type = l_type;
  61. lock.l_whence = SEEK_SET;
  62. lock.l_start = 0;
  63. lock.l_len = 1;
  64. return (fcntl(fd_, cmd, &lock) == 0);
  65. }
  66. bool
  67. InterprocessSyncFile::lock() {
  68. if (is_locked_) {
  69. return (true);
  70. }
  71. if (do_lock(F_SETLKW, F_WRLCK)) {
  72. is_locked_ = true;
  73. return (true);
  74. }
  75. return (false);
  76. }
  77. bool
  78. InterprocessSyncFile::tryLock() {
  79. if (is_locked_) {
  80. return (true);
  81. }
  82. if (do_lock(F_SETLK, F_WRLCK)) {
  83. is_locked_ = true;
  84. return (true);
  85. }
  86. return (false);
  87. }
  88. bool
  89. InterprocessSyncFile::unlock() {
  90. if (!is_locked_) {
  91. return (true);
  92. }
  93. if (do_lock(F_SETLKW, F_UNLCK)) {
  94. is_locked_ = false;
  95. return (true);
  96. }
  97. return (false);
  98. }
  99. } // namespace interprocess
  100. } // namespace log
  101. } // namespace isc