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 != "")