[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/StarryInternet/sysadmin/master/src/TransactionManager.cpp [Back]  [Original]

#include "TransactionManager.h"

#include 
#include 

namespace
{
    log4cxx::LoggerPtr spLogger(log4cxx::Logger::getLogger("TransactionManager"));
}

AllCommitHistories::AllCommitHistories(const std::vector& commits)
  : mCommits(Sort(commits))
  , mMaxCommitId(FindMaxCommitId(commits))
{
}

void AllCommitHistories::StoreCommit(const CommitHistory& commit)
{
    mCommits.emplace_back(commit);
    mMaxCommitId = std::max(mMaxCommitId, commit.mId);
    mMaxCommitId = std::max(mMaxCommitId, commit.mParent);
}

boost::optional AllCommitHistories::GetCommit(CommitHistory::CommitId commitId)
{
    boost::optional maybeCommit;
    for (const auto& commit : mCommits)
    {
        if (commit.mId == commitId)
        {
            maybeCommit = commit;
        }
    }
    return maybeCommit;
}

boost::optional AllCommitHistories::GetChild(CommitHistory::CommitId parentId)
{
    boost::optional maybeCommit;
    for (const auto& commit : mCommits)
    {
        if (commit.mParent == parentId)
        {
            maybeCommit = commit;
        }
    }
    return maybeCommit;
}

boost::optional AllCommitHistories::DropOldestCommit()
{
    boost::optional maybeCommit;
    if (mCommits.size() > 0)
    {
        maybeCommit = mCommits.front();
        mCommits.erase(mCommits.begin());
    }
    return maybeCommit;
}

boost::optional AllCommitHistories::GetMostRecentCommit()
{
    boost::optional maybeCommit;
    if (mCommits.size() > 0)
    {
        maybeCommit = mCommits.back();
    }
    return maybeCommit;
}

//Returns the highest commit id in use. This is not necessarily the commit id of the most recent commit
CommitHistory::CommitId AllCommitHistories::GetHighestCommitId()
{
    return mMaxCommitId;
}

size_t AllCommitHistories::GetCommitCount()
{
    return mCommits.size();
}

std::vector AllCommitHistories::Blame(const ConfigPair::Key& key)
{
    auto getDelta = [key] (const CommitHistory& commit)
    {
        boost::optional maybeDelta;
        for (const auto& delta : commit.mItems)
        {
            if (delta.first.GetKey() == key)
            {
                maybeDelta = delta;
            }
        }
        return maybeDelta;
    };

    std::vector vec;
    for (const auto& commit : mCommits)
    {
        auto configDelta = getDelta(commit);
        if (configDelta)
        {
            BlameDelta blameDelta {commit.mId, commit.mTime, configDelta.get()};
            vec.emplace_back(blameDelta);
        }
    }
    //Reverse the vec so deltas are listed youngest -> oldest
    std::reverse(vec.begin(), vec.end());
    return vec;
}

CommitHistory::CommitId
AllCommitHistories::FindMaxCommitId(const std::vector& unsortedCommits)
{
    CommitHistory::CommitId id = 0;
    for (auto& commit : unsortedCommits)
    {
        id = std::max(id, commit.mId);
        id = std::max(id, commit.mParent);
    }
    return id;
}

boost::optional
AllCommitHistories::FindMostRecentCommit(const std::vector& unsortedCommits)
{
    boost::optional maybeCommit;
    for (const auto& commit : unsortedCommits)
    {
        auto maybeChild = FindChild(commit.mId, unsortedCommits);
        if (!maybeChild)         //The youngest commit won't have a child
        {
            maybeCommit = commit;
        }
    }
    return maybeCommit;
}

boost::optional
AllCommitHistories::FindChild(CommitHistory::CommitId parentId,
                              const std::vector& unsortedCommits)
{
    boost::optional maybeCommit;
    for (const auto& commit : unsortedCommits)
    {
        if (commit.mParent == parentId)
        {
            maybeCommit = commit;
        }
    }
    return maybeCommit;
}

std::list
AllCommitHistories::Sort(const std::vector& unsortedCommits)
{
    std::list sortedCommits;

    auto maybeCurrent = FindMostRecentCommit(unsortedCommits);
    while (maybeCurrent)
    {
        CommitHistory commit = maybeCurrent.get();
        sortedCommits.insert(sortedCommits.begin(), commit);
        maybeCurrent = FindCommit(commit.mParent, unsortedCommits);
    }

    return sortedCommits;
}

boost::optional
AllCommitHistories::FindCommit(CommitHistory::CommitId commitId,
                               const std::vector& unsortedCommits)
{
    boost::optional maybeCommit;
    for (const auto& commit : unsortedCommits)
    {
        if (commit.mId == commitId)
        {
            maybeCommit = commit;
        }
    }
    return maybeCommit;
}

TransactionManager::TransactionManager(IConfigurator* pDb,
                                       IHistoryStorage* pStorage,
                                       size_t maxStorage)
  : mpDb(pDb)
  , mStorage(pStorage)
  , mMaxStorage(maxStorage)
  , mCommitHistory(mStorage->LoadAllCommits())
{
    DropExcessiveCommits();
}

//TODO: In the future AllCommitHistory could be responsible for the local storage as well
size_t TransactionManager::LogCommit(const ConfigPairList& toBeCommitted)
{
    CommitHistory commit;
    CommitHistory::ConfigDeltaList items = GenerateDeltas(toBeCommitted);
    commit.mItems.insert(commit.mItems.begin(), items.begin(), items.end());
    commit.mId = mCommitHistory.GetHighestCommitId() + 1;

    //Assign parent id (defaults to 0 if this is the first commit)
    CommitHistory::CommitId parentId = 0;
    boost::optional parent = mCommitHistory.GetMostRecentCommit();
    if (parent)
    {
        parentId = parent.get().mId;
    }
    commit.mParent = parentId;
    commit.mTime = boost::posix_time::second_clock::local_time();

    mCommitHistory.StoreCommit(commit);
    mStorage->StoreCommit(commit);

    DropExcessiveCommits();

    return commit.mId;
}

folly::Future
TransactionManager::Rollback(CommitHistory::CommitId commitId)
{
    auto maybeCommit = mCommitHistory.GetCommit(commitId);

    if (maybeCommit)
    {
        auto commit = maybeCommit.get();
        if (CanRollback(commit))
        {
            for (const auto& item : commit.mItems)
            {
                if (item.first.GetValue().Empty())
                {
                    mpDb->Erase(item.first.GetKey(), TRANSACTION_HISTORY_ID);
                }
                else
                {
                    mpDb->Set(item.first, TRANSACTION_HISTORY_ID);
                }
            }

            return mpDb->Commit(TRANSACTION_HISTORY_ID).thenValue([commitId](CommitHistory::CommitId)
            {
                LOG4CXX_INFO(spLogger, "Completed rollback of commit " 

Web Proxy Viewer  |  New URL  |  Original Page