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.
This commit is contained in:
Paul Beckingham 2009-03-10 15:21:29 -04:00
parent dc946e175e
commit d174bb1143
8 changed files with 58 additions and 15 deletions

View file

@ -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 ------------------------------

View file

@ -325,6 +325,21 @@ ID Project Pri Description
whenever the shadow file is updated by some task command.
</dd>
<dt>locking</dt>
<dd>
<p>
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".
</p>
<p>
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.
</p>
</dd>
<p>
Note that the command:
</p>

View file

@ -127,6 +127,8 @@
recurring tasks. This column can be added to any custom report.
<li>Added support for "color.recurring" configuration variable which
specifies the color of recurring tasks.
<li>Added support for "locking" configuration variable that controls whether
file locking is used.
</ul>
<p>

View file

@ -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;

View file

@ -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 <T>& 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 <T>::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;
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -51,6 +51,8 @@ public:
int gc ();
int nextId ();
void noLock ();
private:
bool lock (FILE*) const;
bool overwritePending (std::vector <T>&);
@ -62,6 +64,7 @@ private:
std::string mPendingFile;
std::string mCompletedFile;
int mId;
bool mNoLock;
};
#endif

View file

@ -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

View file

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