From d174bb11437ac5201d39626c13c9cc23d3a8e8c1 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Tue, 10 Mar 2009 15:21:29 -0400 Subject: [PATCH] Bug Workaround - locking - Added support for the "locking" configuration variable that disables file locking. This can be helpful to folks who use task on Solaris, and store their task data files on an NFS mount. --- ChangeLog | 2 ++ html/config.html | 15 +++++++++++++++ html/task.html | 2 ++ src/Config.cpp | 13 ++++++++----- src/TDB.cpp | 30 ++++++++++++++++++++++-------- src/TDB.h | 3 +++ src/command.cpp | 4 ++-- src/task.cpp | 4 ++++ 8 files changed, 58 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4dc041060..de3524351 100644 --- a/ChangeLog +++ b/ChangeLog @@ -33,6 +33,8 @@ recurring tasks. This column can be added to any custom report. + Added support for "color.recurring" configuration variable which specifies the color of recurring tasks. + + Added support for "locking" configuration variable that controls whether + file locking is used. ------ old releases ------------------------------ diff --git a/html/config.html b/html/config.html index 20b211fcf..c614f3ad0 100644 --- a/html/config.html +++ b/html/config.html @@ -325,6 +325,21 @@ ID Project Pri Description whenever the shadow file is updated by some task command. +
locking
+
+

+ Determines whether task uses file locking when accessing the pending.data + and completed.data files. Default to "on". Solaris users who store + the task data files on an NFS mount may need to set locking to "off". +

+ +

+ Note that setting this value to "off" is dangerous. It means that + another program may write to the task.pending file when task is + attempting to do the same. +

+
+

Note that the command:

diff --git a/html/task.html b/html/task.html index 04bc81f96..9f4ef60cc 100644 --- a/html/task.html +++ b/html/task.html @@ -127,6 +127,8 @@ recurring tasks. This column can be added to any custom report.
  • Added support for "color.recurring" configuration variable which specifies the color of recurring tasks. +
  • Added support for "locking" configuration variable that controls whether + file locking is used.

    diff --git a/src/Config.cpp b/src/Config.cpp index 643c0ac16..7ac95b1a7 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -132,6 +132,7 @@ void Config::createDefault (const std::string& home) fprintf (out, "color=on\n"); fprintf (out, "due=7\n"); fprintf (out, "nag=You have higher priority tasks.\n"); + fprintf (out, "locking=on\n"); fprintf (out, "color.overdue=bold_red\n"); fprintf (out, "color.due=bold_yellow\n"); @@ -222,11 +223,13 @@ bool Config::get (const std::string& key, bool default_value) { std::string value = lowerCase ((*this)[key]); - if (value == "t" || - value == "true" || - value == "1" || - value == "yes" || - value == "on") + if (value == "t" || + value == "true" || + value == "1" || + value == "yes" || + value == "on" || + value == "enable" || + value == "enabled") return true; return false; diff --git a/src/TDB.cpp b/src/TDB.cpp index 98a67e119..c77febb7a 100644 --- a/src/TDB.cpp +++ b/src/TDB.cpp @@ -38,6 +38,7 @@ TDB::TDB () : mPendingFile ("") , mCompletedFile ("") , mId (1) +, mNoLock (false) { } @@ -289,6 +290,9 @@ bool TDB::modifyT (const T& t) //////////////////////////////////////////////////////////////////////////////// bool TDB::lock (FILE* file) const { + if (mNoLock) + return true; + return flock (fileno (file), LOCK_EX) ? false : true; } @@ -300,8 +304,9 @@ bool TDB::overwritePending (std::vector & all) if ((out = fopen (mPendingFile.c_str (), "w"))) { int retry = 0; - while (flock (fileno (out), LOCK_EX) && ++retry <= 3) - delay (0.25); + if (!mNoLock) + while (flock (fileno (out), LOCK_EX) && ++retry <= 3) + delay (0.1); std::vector ::iterator it; for (it = all.begin (); it != all.end (); ++it) @@ -322,8 +327,9 @@ bool TDB::writePending (const T& t) if ((out = fopen (mPendingFile.c_str (), "a"))) { int retry = 0; - while (flock (fileno (out), LOCK_EX) && ++retry <= 3) - delay (0.25); + if (!mNoLock) + while (flock (fileno (out), LOCK_EX) && ++retry <= 3) + delay (0.1); fputs (t.compose ().c_str (), out); @@ -342,8 +348,9 @@ bool TDB::writeCompleted (const T& t) if ((out = fopen (mCompletedFile.c_str (), "a"))) { int retry = 0; - while (flock (fileno (out), LOCK_EX) && ++retry <= 3) - delay (0.25); + if (!mNoLock) + while (flock (fileno (out), LOCK_EX) && ++retry <= 3) + delay (0.1); fputs (t.compose ().c_str (), out); @@ -367,8 +374,9 @@ bool TDB::readLockedFile ( if ((in = fopen (file.c_str (), "r"))) { int retry = 0; - while (flock (fileno (in), LOCK_EX) && ++retry <= 3) - delay (0.25); + if (!mNoLock) + while (flock (fileno (in), LOCK_EX) && ++retry <= 3) + delay (0.1); char line[T_LINE_MAX]; while (fgets (line, T_LINE_MAX, in)) @@ -432,4 +440,10 @@ int TDB::nextId () } //////////////////////////////////////////////////////////////////////////////// +void TDB::noLock () +{ + mNoLock = true; +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/TDB.h b/src/TDB.h index b354d97f3..49a68fa11 100644 --- a/src/TDB.h +++ b/src/TDB.h @@ -51,6 +51,8 @@ public: int gc (); int nextId (); + void noLock (); + private: bool lock (FILE*) const; bool overwritePending (std::vector &); @@ -62,6 +64,7 @@ private: std::string mPendingFile; std::string mCompletedFile; int mId; + bool mNoLock; }; #endif diff --git a/src/command.cpp b/src/command.cpp index a129323af..0a6e9756a 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -367,8 +367,8 @@ std::string handleVersion (Config& conf) "blanklines color color.active color.due color.overdue color.pri.H " "color.pri.L color.pri.M color.pri.none color.recurring color.tagged " "confirmation curses data.location dateformat default.command " - "default.priority defaultwidth due monthsperline nag newest next oldest " - "project shadow.command shadow.file shadow.notify"; + "default.priority defaultwidth due locking monthsperline nag newest next " + "oldest project shadow.command shadow.file shadow.notify"; // This configuration variable is supported, but not documented. It exists // so that unit tests can force color to be on even when the output from task diff --git a/src/task.cpp b/src/task.cpp index 04c73c3e6..00b21d9cb 100644 --- a/src/task.cpp +++ b/src/task.cpp @@ -299,6 +299,10 @@ int main (int argc, char** argv) std::string dataLocation = expandPath (conf.get ("data.location")); tdb.dataDirectory (dataLocation); + // Allow user override of file locking. Solaris/NFS machines may want this. + if (! conf.get ("locking", true)) + tdb.noLock (); + // Check for silly shadow file settings. std::string shadowFile = expandPath (conf.get ("shadow.file")); if (shadowFile != "")