mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-07-07 20:06:36 +02:00
FF4 - Snapshot
- Implemented TDB::lock, TDB::unlock.
This commit is contained in:
parent
3a9c98d342
commit
f97dff0125
3 changed files with 126 additions and 23 deletions
|
@ -103,8 +103,7 @@ void Context::initialize (int argc, char** argv)
|
|||
tdb.location (expandPath (*path));
|
||||
|
||||
// Allow user override of file locking. Solaris/NFS machines may want this.
|
||||
if (! config.get ("locking", true))
|
||||
tdb.noLock ();
|
||||
tdb.lock (config.get ("locking", true));
|
||||
|
||||
// TODO Load pending.data.
|
||||
// TODO Load completed.data.
|
||||
|
@ -114,11 +113,12 @@ void Context::initialize (int argc, char** argv)
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
int Context::run ()
|
||||
{
|
||||
throw std::string ("unimplemented Context::run");
|
||||
// TODO Dispatch to command handlers.
|
||||
// TODO Auto shadow update.
|
||||
// TODO Auto gc.
|
||||
// TODO tdb.load (Filter);
|
||||
|
||||
throw std::string ("unimplemented Context::run");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,14 +26,45 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <string>
|
||||
#include <sys/file.h>
|
||||
#include "text.h"
|
||||
#include "util.h"
|
||||
#include "TDB.h"
|
||||
#include "task.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// The ctor/dtor do nothing.
|
||||
// The lock/unlock methods hold the file open.
|
||||
// There should be only one commit.
|
||||
//
|
||||
// +- TDB::TDB
|
||||
// |
|
||||
// | +- TDB::lock
|
||||
// | | open
|
||||
// | | [lock]
|
||||
// | |
|
||||
// | | +- TDB::load (Filter)
|
||||
// | | | read all
|
||||
// | | | apply filter
|
||||
// | | | return subset
|
||||
// | | |
|
||||
// | | +- TDB::add (T)
|
||||
// | | |
|
||||
// | | +- TDB::update (T, T')
|
||||
// | | |
|
||||
// | | +- TDB::commit
|
||||
// | | write all
|
||||
// | |
|
||||
// | +- TDB::unlock
|
||||
// | [unlock]
|
||||
// | close
|
||||
// |
|
||||
// +- TDB::~TDB
|
||||
// [TDB::unlock]
|
||||
//
|
||||
TDB::TDB ()
|
||||
: mLock (true)
|
||||
, mAllOpenAndLocked (false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -41,7 +72,13 @@ TDB::TDB ()
|
|||
TDB::TDB (const TDB& other)
|
||||
{
|
||||
throw std::string ("unimplemented TDB::TDB");
|
||||
mLocations = other.mLocations;
|
||||
mLocations = other.mLocations;
|
||||
mLock = other.mLock;
|
||||
mAllOpenAndLocked = false; // Deliberately so.
|
||||
|
||||
// Set all to NULL.
|
||||
foreach (location, mLocations)
|
||||
mLocations[location->first] = NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -50,7 +87,13 @@ TDB& TDB::operator= (const TDB& other)
|
|||
throw std::string ("unimplemented TDB::operator=");
|
||||
if (this != &other)
|
||||
{
|
||||
mLocations = other.mLocations;
|
||||
mLocations = other.mLocations;
|
||||
mLock = other.mLock;
|
||||
mAllOpenAndLocked = false; // Deliberately so.
|
||||
|
||||
// Set all to NULL.
|
||||
foreach (location, mLocations)
|
||||
mLocations[location->first] = NULL;
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
@ -59,6 +102,8 @@ TDB& TDB::operator= (const TDB& other)
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
TDB::~TDB ()
|
||||
{
|
||||
if (mAllOpenAndLocked)
|
||||
unlock ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -69,7 +114,33 @@ void TDB::location (const std::string& path)
|
|||
path +
|
||||
"' does not exist, or is not readable and writable.";
|
||||
|
||||
mLocations.push_back (path);
|
||||
mLocations[path] = NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TDB::lock (bool lockFile /* = true */)
|
||||
{
|
||||
mLock = lockFile;
|
||||
|
||||
foreach (location, mLocations)
|
||||
mLocations[location->first] = openAndLock (location->first);
|
||||
|
||||
mAllOpenAndLocked = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TDB::unlock ()
|
||||
{
|
||||
foreach (location, mLocations)
|
||||
{
|
||||
if (mLocations[location->first] != NULL)
|
||||
{
|
||||
fclose (mLocations[location->first]);
|
||||
mLocations[location->first] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
mAllOpenAndLocked = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -80,6 +151,13 @@ int TDB::load (std::vector <T>& tasks, Filter& filter)
|
|||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// TODO Write to transaction log.
|
||||
void TDB::add (T& after)
|
||||
{
|
||||
throw std::string ("unimplemented TDB::add");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// TODO Write to transaction log.
|
||||
void TDB::update (T& before, T& after)
|
||||
|
@ -101,19 +179,13 @@ void TDB::upgrade ()
|
|||
throw std::string ("unimplemented TDB::upgrade");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TDB::noLock ()
|
||||
{
|
||||
mLock = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TDB::getPendingFiles (std::vector <std::string> files)
|
||||
{
|
||||
files.clear ();
|
||||
|
||||
foreach (location, mLocations)
|
||||
files.push_back (*location + "/pending.data");
|
||||
files.push_back (location->first + "/pending.data");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -122,7 +194,32 @@ void TDB::getCompletedFiles (std::vector <std::string> files)
|
|||
files.clear ();
|
||||
|
||||
foreach (location, mLocations)
|
||||
files.push_back (*location + "/completed.data");
|
||||
files.push_back (location->first + "/completed.data");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
FILE* TDB::openAndLock (const std::string& file)
|
||||
{
|
||||
// Check for access.
|
||||
if (access (file.c_str (), F_OK | R_OK | W_OK))
|
||||
throw std::string ("Task does not have the correct permissions for '") +
|
||||
file + "'.";
|
||||
|
||||
// Open the file.
|
||||
FILE* in = fopen (file.c_str (), "rw");
|
||||
if (!in)
|
||||
throw std::string ("Could not open '") + file + "'.";
|
||||
|
||||
// Lock if desired. Try three times before failing.
|
||||
int retry = 0;
|
||||
if (mLock)
|
||||
while (flock (fileno (in), LOCK_EX) && ++retry <= 3)
|
||||
delay (0.1);
|
||||
|
||||
if (!in)
|
||||
throw std::string ("Could not lock '") + file + "'.";
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#ifndef INCLUDED_TDB
|
||||
#define INCLUDED_TDB
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "Filter.h"
|
||||
|
@ -40,21 +41,26 @@ public:
|
|||
TDB& operator= (const TDB&); // Assignment operator
|
||||
~TDB (); // Destructor
|
||||
|
||||
void location (const std::string&);
|
||||
int load (std::vector <T>&, Filter&);
|
||||
void update (T&, T&);
|
||||
int commit ();
|
||||
void upgrade ();
|
||||
void location (const std::string&);
|
||||
|
||||
void noLock ();
|
||||
void lock (bool lockFile = true);
|
||||
void unlock ();
|
||||
|
||||
int load (std::vector <T>&, Filter&);
|
||||
void add (T&);
|
||||
void update (T&, T&);
|
||||
int commit ();
|
||||
void upgrade ();
|
||||
|
||||
private:
|
||||
void getPendingFiles (std::vector <std::string>);
|
||||
void getCompletedFiles (std::vector <std::string>);
|
||||
void getPendingFiles (std::vector <std::string>);
|
||||
void getCompletedFiles (std::vector <std::string>);
|
||||
FILE* openAndLock (const std::string&);
|
||||
|
||||
private:
|
||||
std::vector <std::string> mLocations;
|
||||
std::map <std::string, FILE*> mLocations;
|
||||
bool mLock;
|
||||
bool mAllOpenAndLocked;
|
||||
|
||||
// TODO Need cache of raw file contents.
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue