Skip to content

Commit

Permalink
#9 TI-1: Move starting and stopping of transactions to commands
Browse files Browse the repository at this point in the history
  • Loading branch information
lauft committed Jul 21, 2018
1 parent 29e3050 commit cfdd368
Show file tree
Hide file tree
Showing 17 changed files with 89 additions and 51 deletions.
66 changes: 26 additions & 40 deletions src/Database.cpp
Expand Up @@ -24,16 +24,11 @@
//
////////////////////////////////////////////////////////////////////////////////

#include <cmake.h>
#include <Database.h>
#include <FS.h>
#include <format.h>
#include <algorithm>
#include <sstream>
#include <iterator>
#include <iomanip>
#include <TransactionsFactory.h>
#include <ctime>

////////////////////////////////////////////////////////////////////////////////
void Database::initialize (const std::string& location)
Expand Down Expand Up @@ -97,8 +92,6 @@ std::vector <std::string> Database::allLines ()
////////////////////////////////////////////////////////////////////////////////
void Database::addInterval (const Interval& interval)
{
startTransaction ();

if (interval.range.is_open ())
{
// Get the index into _files for the appropriate Datafile, which may be
Expand Down Expand Up @@ -127,15 +120,11 @@ void Database::addInterval (const Interval& interval)
recordIntervalAction ("", segmentedInterval.json ());
}
}

endTransaction ();
}

////////////////////////////////////////////////////////////////////////////////
void Database::deleteInterval (const Interval& interval)
{
startTransaction ();

auto intervalRange = interval.range;
for (auto& segment : segmentRange (intervalRange))
{
Expand All @@ -153,8 +142,6 @@ void Database::deleteInterval (const Interval& interval)

recordIntervalAction (segmentedInterval.json (), "");
}

endTransaction ();
}

////////////////////////////////////////////////////////////////////////////////
Expand All @@ -164,8 +151,6 @@ void Database::deleteInterval (const Interval& interval)
// Interval belongs in a different file.
void Database::modifyInterval (const Interval& from, const Interval& to)
{
startTransaction ();

if (!from.empty ())
{
deleteInterval (from);
Expand All @@ -175,58 +160,59 @@ void Database::modifyInterval (const Interval& from, const Interval& to)
{
addInterval (to);
}

endTransaction ();
}

////////////////////////////////////////////////////////////////////////////////
// The _txn member is a reference count, allowing multiple nested transactions.
// This accommodates the Database::modifyInterval call, that in turn calls
// ::addInterval and ::deleteInterval.
void Database::startTransaction ()
{
if (_txn == 0)
if (_currentTransaction != nullptr)
{
_currentTransaction = std::make_shared <Transaction> ();
throw "Subsequent call to start transaction";
}

++_txn;
_currentTransaction = std::make_shared <Transaction> ();
}

////////////////////////////////////////////////////////////////////////////////
// The _txn member is a reference count. The undo data is only written when
// ::endTransaction decrements the counter to zero, therefore the undo command can
// perform multiple atomic steps.
void Database::endTransaction ()
{
--_txn;
if (_txn == 0)
if (_currentTransaction == nullptr)
{
File undo (_location + "/undo.data");
throw "Call to end non-existent transaction";
}

if (undo.open ())
{
undo.append (_currentTransaction->toString());
File undo (_location + "/undo.data");

undo.close ();
_currentTransaction.reset ();
}
else
{
throw format ("Unable to write the undo transaction to {1}", undo._data);
}
if (undo.open ())
{
undo.append (_currentTransaction->toString());

undo.close ();
_currentTransaction.reset ();
}
else
{
throw format ("Unable to write the undo transaction to {1}", undo._data);
}
}

////////////////////////////////////////////////////////////////////////////////
// Record undoable transactions. There are several types:
// Record undoable actions. There are several types:
// interval changes to stored intervals
// config changes to configuration
//
// Actions are only recorded if a transaction is open
//
void Database::recordUndoAction (
const std::string &type,
const std::string &before,
const std::string &after)
{
if (_currentTransaction == nullptr)
{
return;
}

_currentTransaction->addUndoAction (type, before, after);
}

Expand Down
2 changes: 2 additions & 0 deletions src/commands/CmdCancel.cpp
Expand Up @@ -44,7 +44,9 @@ int CmdCancel (
return 0;
}

database.startTransaction ();
database.deleteInterval(latest);
database.endTransaction ();

if (rules.getBoolean ("verbose"))
std::cout << "Canceled active time tracking.\n";
Expand Down
16 changes: 5 additions & 11 deletions src/commands/CmdConfig.cpp
Expand Up @@ -77,9 +77,7 @@ static bool setConfigVariable (
auto before = line;
line = line.substr (0, pos) + name + " = " + value;

database.startTransaction ();
database.recordConfigAction (before, line);
database.endTransaction ();

change = true;
}
Expand Down Expand Up @@ -112,9 +110,7 @@ static bool setConfigVariable (
auto before = line;
line = line.substr (0, pos) + leaf + " " + value;

database.startTransaction ();
database.recordConfigAction (before, line);
database.endTransaction ();

change = true;
}
Expand All @@ -137,9 +133,7 @@ static bool setConfigVariable (
// Add new line.
lines.push_back (name + " = " + json::encode (value));

database.startTransaction ();
database.recordConfigAction ("", lines.back ());
database.endTransaction ();

change = true;
}
Expand All @@ -160,9 +154,7 @@ static bool setConfigVariable (
// Add new line.
lines.push_back (name + " = " + json::encode (value));

database.startTransaction ();
database.recordConfigAction ("", lines.back ());
database.endTransaction ();

change = true;
}
Expand Down Expand Up @@ -212,9 +204,7 @@ static int unsetConfigVariable (
if (! confirmation ||
confirm (format ("Are you sure you want to remove '{1}'?", name)))
{
database.startTransaction ();
database.recordConfigAction (line, "");
database.endTransaction ();

line = "";
change = true;
Expand Down Expand Up @@ -288,13 +278,15 @@ int CmdConfig (
std::string name = words[0];
std::string value;

if (name.empty ())
if (name.empty ()) // is this possible?
{
return CmdShow (rules);
}

bool change = false;

database.startTransaction ();

// timew config name value
// timew config name ""
if (words.size () > 1)
Expand Down Expand Up @@ -338,6 +330,8 @@ int CmdConfig (
}
}

database.endTransaction ();

if (rules.getBoolean ("verbose"))
{
if (change)
Expand Down
4 changes: 4 additions & 0 deletions src/commands/CmdContinue.cpp
Expand Up @@ -73,6 +73,8 @@ int CmdContinue (
Datetime start_time;
Datetime end_time;

database.startTransaction ();

if (filter.range.start.toEpoch () != 0)
{
start_time = filter.range.start;
Expand Down Expand Up @@ -110,6 +112,8 @@ int CmdContinue (
validate (cli, rules, database, to_copy);
database.addInterval (to_copy);

database.endTransaction ();

if (rules.getBoolean ("verbose"))
std::cout << intervalSummarize (database, rules, to_copy);

Expand Down
4 changes: 4 additions & 0 deletions src/commands/CmdDelete.cpp
Expand Up @@ -45,6 +45,8 @@ int CmdDelete (
Interval filter;
auto tracked = getTracked (database, rules, filter);

database.startTransaction ();

bool dirty = true;

for (auto& id : ids)
Expand Down Expand Up @@ -77,6 +79,8 @@ int CmdDelete (
std::cout << "Deleted @" << id << '\n';
}

database.endTransaction ();

return 0;
}

Expand Down
4 changes: 4 additions & 0 deletions src/commands/CmdFill.cpp
Expand Up @@ -46,6 +46,8 @@ int CmdFill (
Interval filter;
auto tracked = getTracked (database, rules, filter);

database.startTransaction ();

// Apply tags to ids.
for (auto& id : ids)
{
Expand All @@ -65,6 +67,8 @@ int CmdFill (
// Note: Feedback generated inside autoFill().
}

database.endTransaction ();

return 0;
}

Expand Down
4 changes: 4 additions & 0 deletions src/commands/CmdJoin.cpp
Expand Up @@ -60,6 +60,8 @@ int CmdJoin (

}

database.startTransaction ();

auto first_id = std::min (*ids.begin (), *ids.end ());
auto second_id = std::max (*ids.begin (), *ids.end ());

Expand All @@ -77,6 +79,8 @@ int CmdJoin (
validate (cli, rules, database, combined);
database.addInterval (combined);

database.endTransaction ();

if (rules.getBoolean ("verbose"))
std::cout << "Joined @" << first_id << " and @" << second_id << '\n';

Expand Down
4 changes: 4 additions & 0 deletions src/commands/CmdLengthen.cpp
Expand Up @@ -53,6 +53,8 @@ int CmdLengthen (
delta = arg.attribute ("raw");
}

database.startTransaction ();

// Load the data.
// Note: There is no filter.
Interval filter;
Expand Down Expand Up @@ -102,6 +104,8 @@ int CmdLengthen (
std::cout << "Lengthened @" << id << " by " << dur.formatHours () << '\n';
}

database.endTransaction ();

return 0;
}

Expand Down
4 changes: 4 additions & 0 deletions src/commands/CmdMove.cpp
Expand Up @@ -51,6 +51,8 @@ int CmdMove (
throw std::string ("ID must be specified. See 'timew help move'.");
}

database.startTransaction ();

int id = *ids.begin ();

std::string new_start;
Expand Down Expand Up @@ -107,6 +109,8 @@ int CmdMove (
validate (cli, rules, database, i);
database.addInterval (i);

database.endTransaction ();

if (rules.getBoolean ("verbose"))
std::cout << "Moved @" << id << " to " << i.range.start.toISOLocalExtended () << '\n';

Expand Down
4 changes: 4 additions & 0 deletions src/commands/CmdResize.cpp
Expand Up @@ -51,6 +51,8 @@ int CmdResize (
delta = arg.attribute ("raw");
}

database.startTransaction ();

// Load the data.
// Note: There is no filter.
Interval filter;
Expand All @@ -77,6 +79,8 @@ int CmdResize (
std::cout << "Resized @" << id << " to " << dur.formatHours () << '\n';
}

database.endTransaction ();

return 0;
}

Expand Down
4 changes: 4 additions & 0 deletions src/commands/CmdShorten.cpp
Expand Up @@ -51,6 +51,8 @@ int CmdShorten (
delta = arg.attribute ("raw");
}

database.startTransaction ();

// Load the data.
// Note: There is no filter.
Interval filter;
Expand Down Expand Up @@ -103,6 +105,8 @@ int CmdShorten (
std::cout << "Shortened @" << id << " by " << dur.formatHours () << '\n';
}

database.endTransaction ();

return 0;
}

Expand Down
4 changes: 4 additions & 0 deletions src/commands/CmdSplit.cpp
Expand Up @@ -48,6 +48,8 @@ int CmdSplit (
Interval filter;
auto tracked = getTracked (database, rules, filter);

database.startTransaction ();

// Apply tags to ids.
for (auto& id : ids)
{
Expand Down Expand Up @@ -84,6 +86,8 @@ int CmdSplit (
std::cout << "Split @" << id << '\n';
}

database.endTransaction ();

return 0;
}

Expand Down

0 comments on commit cfdd368

Please sign in to comment.