logic: allow manipulating multiple nodes in single logic
Change-Id: Iaa2a2b08e891d41c9aa71c13ffc531bef406b6d8
This commit is contained in:
1 parent
3573e131d2
commit
8c095fd188
4 files changed
+406
-175
No files matched your search
+137
-58
@@ -50,6 +50,7 @@ int Logic::m_instanceCounter = 0;
|
||||
#endif
|
||||
|
||||
const ndn::Name Logic::DEFAULT_NAME;
|
||||
const ndn::Name Logic::EMPTY_NAME;
|
||||
const ndn::shared_ptr<ndn::Validator> Logic::DEFAULT_VALIDATOR;
|
||||
const time::steady_clock::Duration Logic::DEFAULT_RESET_TIMER = time::seconds(0);
|
||||
const time::steady_clock::Duration Logic::DEFAULT_CANCEL_RESET_TIMER = time::milliseconds(500);
|
||||
@@ -62,9 +63,9 @@ const ndn::name::Component Logic::RESET_COMPONENT("reset");
|
||||
|
||||
Logic::Logic(ndn::Face& face,
|
||||
const Name& syncPrefix,
|
||||
const Name& userPrefix,
|
||||
const Name& defaultUserPrefix,
|
||||
const UpdateCallback& onUpdate,
|
||||
const Name& signingId,
|
||||
const Name& defaultSigningId,
|
||||
ndn::shared_ptr<ndn::Validator> validator,
|
||||
const time::steady_clock::Duration& resetTimer,
|
||||
const time::steady_clock::Duration& cancelResetTimer,
|
||||
@@ -73,7 +74,7 @@ Logic::Logic(ndn::Face& face,
|
||||
const time::milliseconds& syncReplyFreshness)
|
||||
: m_face(face)
|
||||
, m_syncPrefix(syncPrefix)
|
||||
, m_userPrefix(userPrefix)
|
||||
, m_defaultUserPrefix(defaultUserPrefix)
|
||||
, m_interestTable(m_face.getIoService())
|
||||
, m_outstandingInterestId(0)
|
||||
, m_isInReset(false)
|
||||
@@ -88,7 +89,7 @@ Logic::Logic(ndn::Face& face,
|
||||
, m_resetInterestLifetime(resetInterestLifetime)
|
||||
, m_syncInterestLifetime(syncInterestLifetime)
|
||||
, m_syncReplyFreshness(syncReplyFreshness)
|
||||
, m_signingId(signingId)
|
||||
, m_defaultSigningId(defaultSigningId)
|
||||
, m_validator(validator)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
@@ -97,6 +98,9 @@ Logic::Logic(ndn::Face& face,
|
||||
|
||||
_LOG_DEBUG_ID(">> Logic::Logic");
|
||||
|
||||
addUserNode(m_defaultUserPrefix, m_defaultSigningId);
|
||||
|
||||
|
||||
m_syncReset = m_syncPrefix;
|
||||
m_syncReset.append("reset");
|
||||
|
||||
@@ -106,7 +110,6 @@ Logic::Logic(ndn::Face& face,
|
||||
bind(&Logic::onSyncInterest, this, _1, _2),
|
||||
bind(&Logic::onSyncRegisterFailed, this, _1, _2));
|
||||
|
||||
setUserPrefix(m_userPrefix);
|
||||
|
||||
_LOG_DEBUG_ID("<< Logic::Logic");
|
||||
}
|
||||
@@ -144,56 +147,132 @@ Logic::reset()
|
||||
}
|
||||
|
||||
void
|
||||
Logic::setUserPrefix(const Name& userPrefix)
|
||||
Logic::setDefaultUserPrefix(const Name& defaultUserPrefix)
|
||||
{
|
||||
m_userPrefix = userPrefix;
|
||||
|
||||
m_sessionName = m_userPrefix;
|
||||
m_sessionName.appendNumber(ndn::time::toUnixTimestamp(ndn::time::system_clock::now()).count());
|
||||
|
||||
m_seqNo = 0;
|
||||
|
||||
reset();
|
||||
if (defaultUserPrefix != EMPTY_NAME) {
|
||||
if (m_nodeList.find(defaultUserPrefix) != m_nodeList.end()) {
|
||||
m_defaultUserPrefix = defaultUserPrefix;
|
||||
m_defaultSigningId = m_nodeList[defaultUserPrefix].signingId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Logic::updateSeqNo(const SeqNo& seqNo)
|
||||
Logic::addUserNode(const Name& userPrefix, const Name& signingId)
|
||||
{
|
||||
_LOG_DEBUG_ID(">> Logic::updateSeqNo");
|
||||
_LOG_DEBUG_ID("seqNo: " << seqNo << " m_seqNo: " << m_seqNo);
|
||||
if (seqNo < m_seqNo || seqNo == 0)
|
||||
if (userPrefix == EMPTY_NAME)
|
||||
return;
|
||||
if (m_defaultUserPrefix == EMPTY_NAME) {
|
||||
m_defaultUserPrefix = userPrefix;
|
||||
m_defaultSigningId = signingId;
|
||||
}
|
||||
if (m_nodeList.find(userPrefix) == m_nodeList.end()) {
|
||||
m_nodeList[userPrefix].userPrefix = userPrefix;
|
||||
m_nodeList[userPrefix].signingId = signingId;
|
||||
Name sessionName = userPrefix;
|
||||
sessionName.appendNumber(ndn::time::toUnixTimestamp(ndn::time::system_clock::now()).count());
|
||||
m_nodeList[userPrefix].sessionName = sessionName;
|
||||
m_nodeList[userPrefix].seqNo = 0;
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
m_seqNo = seqNo;
|
||||
|
||||
_LOG_DEBUG_ID("updateSeqNo: m_seqNo " << m_seqNo);
|
||||
|
||||
if (!m_isInReset) {
|
||||
_LOG_DEBUG_ID("updateSeqNo: not in Reset ");
|
||||
ndn::ConstBufferPtr previousRoot = m_state.getRootDigest();
|
||||
{
|
||||
using namespace CryptoPP;
|
||||
|
||||
std::string hash;
|
||||
StringSource(previousRoot->buf(), previousRoot->size(), true,
|
||||
new HexEncoder(new StringSink(hash), false));
|
||||
_LOG_DEBUG_ID("Hash: " << hash);
|
||||
void
|
||||
Logic::removeUserNode(const Name& userPrefix)
|
||||
{
|
||||
auto userNode = m_nodeList.find(userPrefix);
|
||||
if (userNode != m_nodeList.end()) {
|
||||
m_nodeList.erase(userNode);
|
||||
if (m_defaultUserPrefix == userPrefix) {
|
||||
if (!m_nodeList.empty()) {
|
||||
m_defaultUserPrefix = m_nodeList.begin()->second.userPrefix;
|
||||
m_defaultSigningId = m_nodeList.begin()->second.signingId;
|
||||
}
|
||||
else {
|
||||
m_defaultUserPrefix = EMPTY_NAME;
|
||||
m_defaultSigningId = DEFAULT_NAME;
|
||||
}
|
||||
}
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
bool isInserted = false;
|
||||
bool isUpdated = false;
|
||||
SeqNo oldSeq;
|
||||
boost::tie(isInserted, isUpdated, oldSeq) = m_state.update(m_sessionName, seqNo);
|
||||
const Name&
|
||||
Logic::getSessionName(Name prefix)
|
||||
{
|
||||
if (prefix == EMPTY_NAME)
|
||||
prefix = m_defaultUserPrefix;
|
||||
auto node = m_nodeList.find(prefix);
|
||||
if (node != m_nodeList.end())
|
||||
return node->second.sessionName;
|
||||
else
|
||||
throw Error("Refer to non-existent node:" + prefix.toUri());
|
||||
}
|
||||
|
||||
_LOG_DEBUG_ID("Insert: " << std::boolalpha << isInserted);
|
||||
_LOG_DEBUG_ID("Updated: " << std::boolalpha << isUpdated);
|
||||
if (isInserted || isUpdated) {
|
||||
DiffStatePtr commit = make_shared<DiffState>();
|
||||
commit->update(m_sessionName, seqNo);
|
||||
commit->setRootDigest(m_state.getRootDigest());
|
||||
insertToDiffLog(commit, previousRoot);
|
||||
const SeqNo&
|
||||
Logic::getSeqNo(Name prefix)
|
||||
{
|
||||
if (prefix == EMPTY_NAME)
|
||||
prefix = m_defaultUserPrefix;
|
||||
auto node = m_nodeList.find(prefix);
|
||||
if (node != m_nodeList.end())
|
||||
return node->second.seqNo;
|
||||
else
|
||||
throw Logic::Error("Refer to non-existent node:" + prefix.toUri());
|
||||
|
||||
satisfyPendingSyncInterests(commit);
|
||||
}
|
||||
|
||||
void
|
||||
Logic::updateSeqNo(const SeqNo& seqNo, const Name &updatePrefix)
|
||||
{
|
||||
Name prefix;
|
||||
if (updatePrefix == EMPTY_NAME) {
|
||||
if (m_defaultUserPrefix == EMPTY_NAME)
|
||||
return;
|
||||
prefix = m_defaultUserPrefix;
|
||||
}
|
||||
else
|
||||
prefix = updatePrefix;
|
||||
|
||||
auto it = m_nodeList.find(prefix);
|
||||
if (it != m_nodeList.end()) {
|
||||
NodeInfo& node = it->second;
|
||||
_LOG_DEBUG_ID(">> Logic::updateSeqNo");
|
||||
_LOG_DEBUG_ID("seqNo: " << seqNo << " m_seqNo: " << node.seqNo);
|
||||
if (seqNo < node.seqNo || seqNo == 0)
|
||||
return;
|
||||
|
||||
node.seqNo = seqNo;
|
||||
_LOG_DEBUG_ID("updateSeqNo: m_seqNo " << node.seqNo);
|
||||
|
||||
if (!m_isInReset) {
|
||||
_LOG_DEBUG_ID("updateSeqNo: not in Reset ");
|
||||
ndn::ConstBufferPtr previousRoot = m_state.getRootDigest();
|
||||
{
|
||||
using namespace CryptoPP;
|
||||
|
||||
std::string hash;
|
||||
StringSource(previousRoot->buf(), previousRoot->size(), true,
|
||||
new HexEncoder(new StringSink(hash), false));
|
||||
_LOG_DEBUG_ID("Hash: " << hash);
|
||||
}
|
||||
|
||||
bool isInserted = false;
|
||||
bool isUpdated = false;
|
||||
SeqNo oldSeq;
|
||||
boost::tie(isInserted, isUpdated, oldSeq) = m_state.update(node.sessionName,
|
||||
node.seqNo);
|
||||
|
||||
_LOG_DEBUG_ID("Insert: " << std::boolalpha << isInserted);
|
||||
_LOG_DEBUG_ID("Updated: " << std::boolalpha << isUpdated);
|
||||
if (isInserted || isUpdated) {
|
||||
DiffStatePtr commit = make_shared<DiffState>();
|
||||
commit->update(node.sessionName, node.seqNo);
|
||||
commit->setRootDigest(m_state.getRootDigest());
|
||||
insertToDiffLog(commit, previousRoot);
|
||||
|
||||
satisfyPendingSyncInterests(prefix, commit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -341,7 +420,7 @@ Logic::processSyncInterest(const shared_ptr<const Interest>& interest,
|
||||
// If the digest of incoming interest is an "empty" digest
|
||||
if (digest == EMPTY_DIGEST) {
|
||||
_LOG_DEBUG_ID("Poor guy, he knows nothing");
|
||||
sendSyncData(name, m_state);
|
||||
sendSyncData(m_defaultUserPrefix, name, m_state);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -349,7 +428,7 @@ Logic::processSyncInterest(const shared_ptr<const Interest>& interest,
|
||||
// If the digest of incoming interest can be found from the log
|
||||
if (stateIter != m_log.end()) {
|
||||
_LOG_DEBUG_ID("It is ok, you are so close");
|
||||
sendSyncData(name, *(*stateIter)->diff());
|
||||
sendSyncData(m_defaultUserPrefix, name, *(*stateIter)->diff());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -370,7 +449,7 @@ Logic::processSyncInterest(const shared_ptr<const Interest>& interest,
|
||||
// OK, nobody is helping us, just tell the truth.
|
||||
_LOG_DEBUG_ID("OK, nobody is helping us, just tell the truth");
|
||||
m_interestTable.erase(digest);
|
||||
sendSyncData(name, m_state);
|
||||
sendSyncData(m_defaultUserPrefix, name, m_state);
|
||||
}
|
||||
|
||||
_LOG_DEBUG_ID("<< Logic::processSyncInterest");
|
||||
@@ -389,7 +468,6 @@ Logic::processSyncData(const Name& name,
|
||||
const Block& syncReplyBlock)
|
||||
{
|
||||
_LOG_DEBUG_ID(">> Logic::processSyncData");
|
||||
|
||||
DiffStatePtr commit = make_shared<DiffState>();
|
||||
ndn::ConstBufferPtr previousRoot = m_state.getRootDigest();
|
||||
|
||||
@@ -411,7 +489,6 @@ Logic::processSyncData(const Name& name,
|
||||
bool isUpdated = false;
|
||||
SeqNo oldSeq;
|
||||
boost::tie(isInserted, isUpdated, oldSeq) = m_state.update(info, seq);
|
||||
|
||||
if (isInserted || isUpdated) {
|
||||
commit->update(info, seq);
|
||||
|
||||
@@ -451,7 +528,7 @@ Logic::processSyncData(const Name& name,
|
||||
}
|
||||
|
||||
void
|
||||
Logic::satisfyPendingSyncInterests(ConstDiffStatePtr commit)
|
||||
Logic::satisfyPendingSyncInterests(const Name& updatedPrefix, ConstDiffStatePtr commit)
|
||||
{
|
||||
_LOG_DEBUG_ID(">> Logic::satisfyPendingSyncInterests");
|
||||
try {
|
||||
@@ -459,11 +536,10 @@ Logic::satisfyPendingSyncInterests(ConstDiffStatePtr commit)
|
||||
for (InterestTable::const_iterator it = m_interestTable.begin();
|
||||
it != m_interestTable.end(); it++) {
|
||||
ConstUnsatisfiedInterestPtr request = *it;
|
||||
|
||||
if (request->isUnknown)
|
||||
sendSyncData(request->interest->getName(), m_state);
|
||||
sendSyncData(updatedPrefix, request->interest->getName(), m_state);
|
||||
else
|
||||
sendSyncData(request->interest->getName(), *commit);
|
||||
sendSyncData(updatedPrefix, request->interest->getName(), *commit);
|
||||
}
|
||||
m_interestTable.clear();
|
||||
}
|
||||
@@ -548,17 +624,18 @@ Logic::sendSyncInterest()
|
||||
}
|
||||
|
||||
void
|
||||
Logic::sendSyncData(const Name& name, const State& state)
|
||||
Logic::sendSyncData(const Name& nodePrefix, const Name& name, const State& state)
|
||||
{
|
||||
_LOG_DEBUG_ID(">> Logic::sendSyncData");
|
||||
shared_ptr<Data> syncReply = make_shared<Data>(name);
|
||||
syncReply->setContent(state.wireEncode());
|
||||
syncReply->setFreshnessPeriod(m_syncReplyFreshness);
|
||||
|
||||
if (m_signingId.empty())
|
||||
if (m_nodeList.find(nodePrefix) == m_nodeList.end())
|
||||
return;
|
||||
if (m_nodeList[nodePrefix].signingId.empty())
|
||||
m_keyChain.sign(*syncReply);
|
||||
else
|
||||
m_keyChain.signByIdentity(*syncReply, m_signingId);
|
||||
m_keyChain.signByIdentity(*syncReply, m_nodeList[nodePrefix].signingId);
|
||||
|
||||
m_face.put(*syncReply);
|
||||
|
||||
@@ -589,7 +666,9 @@ Logic::cancelReset()
|
||||
return;
|
||||
|
||||
m_isInReset = false;
|
||||
updateSeqNo(m_seqNo);
|
||||
for (const auto& node : m_nodeList) {
|
||||
updateSeqNo(node.second.seqNo, node.first);
|
||||
}
|
||||
_LOG_DEBUG_ID("<< Logic::cancelReset");
|
||||
}
|
||||
|
||||
|
||||
+77
-23
@@ -27,7 +27,7 @@
|
||||
|
||||
#include "boost-header.h"
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <ndn-cxx/face.hpp>
|
||||
#include <ndn-cxx/util/scheduler.hpp>
|
||||
@@ -48,6 +48,14 @@ namespace chronosync {
|
||||
* Instances of this class is usually used as elements of some containers
|
||||
* such as std::vector, thus it is copyable.
|
||||
*/
|
||||
class NodeInfo {
|
||||
public:
|
||||
Name userPrefix;
|
||||
Name signingId;
|
||||
Name sessionName;
|
||||
SeqNo seqNo;
|
||||
};
|
||||
|
||||
class MissingDataInfo
|
||||
{
|
||||
public:
|
||||
@@ -72,6 +80,17 @@ typedef function<void(const std::vector<MissingDataInfo>&)> UpdateCallback;
|
||||
*/
|
||||
class Logic : noncopyable
|
||||
{
|
||||
public:
|
||||
class Error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
Error(const std::string& what)
|
||||
: std::runtime_error(what)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
static const time::steady_clock::Duration DEFAULT_RESET_TIMER;
|
||||
static const time::steady_clock::Duration DEFAULT_CANCEL_RESET_TIMER;
|
||||
@@ -83,8 +102,9 @@ public:
|
||||
* @brief Constructor
|
||||
*
|
||||
* @param syncPrefix The prefix of the sync group
|
||||
* @param userPrefix The prefix of the user who owns the session
|
||||
* @param defaultUserPrefix The prefix of the first user added to this session
|
||||
* @param onUpdate The callback function to handle state updates
|
||||
* @param defaultSigningId The signing Id of the default user
|
||||
* @param validator The validator for packet validation
|
||||
* @param resetTimer The timer to periodically send Reset Interest
|
||||
* @param syncReplyFreshness The FreshnessPeriod of sync reply
|
||||
@@ -94,9 +114,9 @@ public:
|
||||
*/
|
||||
Logic(ndn::Face& face,
|
||||
const Name& syncPrefix,
|
||||
const Name& userPrefix,
|
||||
const Name& defaultUserPrefix,
|
||||
const UpdateCallback& onUpdate,
|
||||
const Name& signingId = DEFAULT_NAME,
|
||||
const Name& defaultSigningId = DEFAULT_NAME,
|
||||
ndn::shared_ptr<ndn::Validator> validator = DEFAULT_VALIDATOR,
|
||||
const time::steady_clock::Duration& resetTimer = DEFAULT_RESET_TIMER,
|
||||
const time::steady_clock::Duration& cancelResetTimer = DEFAULT_CANCEL_RESET_TIMER,
|
||||
@@ -113,36 +133,67 @@ public:
|
||||
/**
|
||||
* @brief Set user prefix
|
||||
*
|
||||
* This method will also change the session name and trigger reset.
|
||||
* This method will also change the default user and signing Id of that user.
|
||||
*
|
||||
* @param userPrefix The prefix of user.
|
||||
* @param defaultUserPrefix The prefix of user.
|
||||
*/
|
||||
void
|
||||
setUserPrefix(const Name& userPrefix);
|
||||
setDefaultUserPrefix(const Name& defaultUserPrefix);
|
||||
|
||||
/// @brief Get the name of the local session.
|
||||
/// @brief Get the name of default user.
|
||||
const Name&
|
||||
getSessionName() const
|
||||
getDefaultUserPrefix() const
|
||||
{
|
||||
return m_sessionName;
|
||||
return m_defaultUserPrefix;
|
||||
}
|
||||
|
||||
/// @brief Get current seqNo of the local session.
|
||||
/**
|
||||
* @brief Add user node into the local session.
|
||||
*
|
||||
* This method also reset after adding
|
||||
*
|
||||
* @param userPrefix prefix of the added node
|
||||
* @param signingId signing Id of the added node
|
||||
*/
|
||||
void
|
||||
addUserNode(const Name& userPrefix, const Name& signingId = DEFAULT_NAME);
|
||||
|
||||
/// @brief remove the node from the local session
|
||||
void
|
||||
removeUserNode(const Name& userPrefix);
|
||||
|
||||
/**
|
||||
* @brief Get the name of the local session.
|
||||
*
|
||||
* This method gets the session name according to prefix, if prefix is not specified,
|
||||
* it returns the session name of default user.
|
||||
*
|
||||
* @param prefix prefix of the node
|
||||
*/
|
||||
const Name&
|
||||
getSessionName(Name prefix = EMPTY_NAME);
|
||||
|
||||
/**
|
||||
* @brief Get current seqNo of the local session.
|
||||
*
|
||||
* This method gets the seqNo according to prefix, if prefix is not specified,
|
||||
* it returns the seqNo of default user.
|
||||
*
|
||||
* @param prefix prefix of the node
|
||||
*/
|
||||
const SeqNo&
|
||||
getSeqNo() const
|
||||
{
|
||||
return m_seqNo;
|
||||
}
|
||||
getSeqNo(Name prefix = EMPTY_NAME);
|
||||
|
||||
/**
|
||||
* @brief Update the seqNo of the local session
|
||||
*
|
||||
* The method updates the existing seqNo with the supplied seqNo.
|
||||
* The method updates the existing seqNo with the supplied seqNo and prefix.
|
||||
*
|
||||
* @param seq The new seqNo.
|
||||
* @param updatePrefix The prefix of node to update.
|
||||
*/
|
||||
void
|
||||
updateSeqNo(const SeqNo& seq);
|
||||
updateSeqNo(const SeqNo& seq, const Name& updatePrefix = EMPTY_NAME);
|
||||
|
||||
/// @brief Get root digest of current sync tree
|
||||
ndn::ConstBufferPtr
|
||||
@@ -168,6 +219,7 @@ CHRONOSYNC_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
|
||||
return m_state;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Callback to handle Sync Interest
|
||||
@@ -304,7 +356,7 @@ private:
|
||||
* @param commit The diff.
|
||||
*/
|
||||
void
|
||||
satisfyPendingSyncInterests(ConstDiffStatePtr commit);
|
||||
satisfyPendingSyncInterests(const Name& updatedPrefix, ConstDiffStatePtr commit);
|
||||
|
||||
/// @brief Helper method to send normal Sync Interest
|
||||
void
|
||||
@@ -316,7 +368,7 @@ private:
|
||||
|
||||
/// @brief Helper method to send Sync Reply
|
||||
void
|
||||
sendSyncData(const Name& name, const State& state);
|
||||
sendSyncData(const Name& nodePrefix, const Name& name, const State& state);
|
||||
|
||||
/**
|
||||
* @brief Unset reset status
|
||||
@@ -332,9 +384,11 @@ private:
|
||||
|
||||
public:
|
||||
static const ndn::Name DEFAULT_NAME;
|
||||
static const ndn::Name EMPTY_NAME;
|
||||
static const ndn::shared_ptr<ndn::Validator> DEFAULT_VALIDATOR;
|
||||
|
||||
private:
|
||||
typedef std::unordered_map<ndn::Name, NodeInfo> NodeList;
|
||||
|
||||
static const ndn::ConstBufferPtr EMPTY_DIGEST;
|
||||
static const ndn::name::Component RESET_COMPONENT;
|
||||
@@ -344,11 +398,10 @@ private:
|
||||
Name m_syncPrefix;
|
||||
const ndn::RegisteredPrefixId* m_syncRegisteredPrefixId;
|
||||
Name m_syncReset;
|
||||
Name m_userPrefix;
|
||||
Name m_defaultUserPrefix;
|
||||
|
||||
// State
|
||||
Name m_sessionName;
|
||||
SeqNo m_seqNo;
|
||||
NodeList m_nodeList;
|
||||
State m_state;
|
||||
DiffStateContainer m_log;
|
||||
InterestTable m_interestTable;
|
||||
@@ -382,10 +435,11 @@ private:
|
||||
time::milliseconds m_syncReplyFreshness;
|
||||
|
||||
// Security
|
||||
ndn::Name m_signingId;
|
||||
ndn::Name m_defaultSigningId;
|
||||
ndn::KeyChain m_keyChain;
|
||||
ndn::shared_ptr<ndn::Validator> m_validator;
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
int m_instanceId;
|
||||
static int m_instanceCounter;
|
||||
|
||||
@@ -59,12 +59,6 @@ public:
|
||||
logic.updateSeqNo(seqNo);
|
||||
}
|
||||
|
||||
void
|
||||
check(const Name& sessionName, const SeqNo& seqNo)
|
||||
{
|
||||
BOOST_CHECK_EQUAL(map[sessionName], seqNo);
|
||||
}
|
||||
|
||||
Logic logic;
|
||||
std::map<Name, SeqNo> map;
|
||||
};
|
||||
@@ -86,30 +80,6 @@ public:
|
||||
faces[2] = make_shared<ndn::Face>(ref(io));
|
||||
}
|
||||
|
||||
void
|
||||
createHandler(size_t idx)
|
||||
{
|
||||
handler[idx] = make_shared<Handler>(ref(*faces[idx]), syncPrefix, userPrefix[idx]);
|
||||
}
|
||||
|
||||
void
|
||||
updateSeqNo(size_t idx, const SeqNo& seqNo)
|
||||
{
|
||||
handler[idx]->updateSeqNo(seqNo);
|
||||
}
|
||||
|
||||
void
|
||||
checkSeqNo(size_t sIdx, size_t dIdx, const SeqNo& seqNo)
|
||||
{
|
||||
handler[sIdx]->check(handler[dIdx]->logic.getSessionName(), seqNo);
|
||||
}
|
||||
|
||||
void
|
||||
terminate()
|
||||
{
|
||||
io.stop();
|
||||
}
|
||||
|
||||
Name syncPrefix;
|
||||
Name userPrefix[3];
|
||||
|
||||
@@ -138,31 +108,27 @@ BOOST_AUTO_TEST_CASE(Constructor)
|
||||
BOOST_AUTO_TEST_CASE(TwoBasic)
|
||||
{
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(100),
|
||||
bind(&LogicFixture::createHandler, this, 0));
|
||||
[this] { handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(200),
|
||||
bind(&LogicFixture::createHandler, this, 1));
|
||||
[this] { handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(300),
|
||||
bind(&LogicFixture::updateSeqNo, this, 0, 1));
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(300), [this] { handler[0]->updateSeqNo(1); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(1000),
|
||||
bind(&LogicFixture::checkSeqNo, this, 1, 0, 1));
|
||||
[this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(1100),
|
||||
bind(&LogicFixture::updateSeqNo, this, 0, 2));
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(1100), [this] { handler[0]->updateSeqNo(2); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(1800),
|
||||
bind(&LogicFixture::checkSeqNo, this, 1, 0, 2));
|
||||
[this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 2); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(1900),
|
||||
bind(&LogicFixture::updateSeqNo, this, 1, 2));
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(1900), [this] { handler[1]->updateSeqNo(2); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(2600),
|
||||
bind(&LogicFixture::checkSeqNo, this, 0, 1, 2));
|
||||
[this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(2800),
|
||||
bind(&LogicFixture::terminate, this));
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(2800), [this] { io.stop(); });
|
||||
|
||||
io.run();
|
||||
}
|
||||
@@ -170,43 +136,39 @@ BOOST_AUTO_TEST_CASE(TwoBasic)
|
||||
BOOST_AUTO_TEST_CASE(ThreeBasic)
|
||||
{
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(100),
|
||||
bind(&LogicFixture::createHandler, this, 0));
|
||||
[this] { handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(200),
|
||||
bind(&LogicFixture::createHandler, this, 1));
|
||||
[this] { handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(300),
|
||||
bind(&LogicFixture::createHandler, this, 2));
|
||||
[this] { handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(500),
|
||||
bind(&LogicFixture::updateSeqNo, this, 0, 1));
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(500), [this] { handler[0]->updateSeqNo(1); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(1400),
|
||||
bind(&LogicFixture::checkSeqNo, this, 1, 0, 1));
|
||||
[this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(1450),
|
||||
bind(&LogicFixture::checkSeqNo, this, 2, 0, 1));
|
||||
[this] { BOOST_CHECK_EQUAL(handler[2]->map[handler[0]->logic.getSessionName()], 1); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(1500),
|
||||
bind(&LogicFixture::updateSeqNo, this, 1, 2));
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(1500), [this] { handler[1]->updateSeqNo(2); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(2400),
|
||||
bind(&LogicFixture::checkSeqNo, this, 0, 1, 2));
|
||||
[this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(2450),
|
||||
bind(&LogicFixture::checkSeqNo, this, 2, 1, 2));
|
||||
[this] { BOOST_CHECK_EQUAL(handler[2]->map[handler[1]->logic.getSessionName()], 2); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(2500),
|
||||
bind(&LogicFixture::updateSeqNo, this, 2, 4));
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(2500), [this] { handler[2]->updateSeqNo(4); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(4400),
|
||||
bind(&LogicFixture::checkSeqNo, this, 0, 2, 4));
|
||||
[this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(4450),
|
||||
bind(&LogicFixture::checkSeqNo, this, 1, 2, 4));
|
||||
[this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(4500),
|
||||
bind(&LogicFixture::terminate, this));
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(4500), [this] { io.stop(); });
|
||||
|
||||
io.run();
|
||||
}
|
||||
@@ -214,44 +176,40 @@ BOOST_AUTO_TEST_CASE(ThreeBasic)
|
||||
BOOST_AUTO_TEST_CASE(ResetRecover)
|
||||
{
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(100),
|
||||
bind(&LogicFixture::createHandler, this, 0));
|
||||
[this] { handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(200),
|
||||
bind(&LogicFixture::createHandler, this, 1));
|
||||
[this] { handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(500),
|
||||
bind(&LogicFixture::updateSeqNo, this, 0, 1));
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(500), [this] { handler[0]->updateSeqNo(1); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(1400),
|
||||
bind(&LogicFixture::checkSeqNo, this, 1, 0, 1));
|
||||
[this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(1500),
|
||||
bind(&LogicFixture::updateSeqNo, this, 1, 2));
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(1500), [this] { handler[1]->updateSeqNo(2); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(2400),
|
||||
bind(&LogicFixture::checkSeqNo, this, 0, 1, 2));
|
||||
[this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(2500),
|
||||
bind(&LogicFixture::createHandler, this, 2));
|
||||
[this] { handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(3000),
|
||||
bind(&LogicFixture::checkSeqNo, this, 1, 0, 1));
|
||||
[this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(3050),
|
||||
bind(&LogicFixture::checkSeqNo, this, 0, 1, 2));
|
||||
[this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(3100),
|
||||
bind(&LogicFixture::updateSeqNo, this, 2, 4));
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(3100), [this] { handler[2]->updateSeqNo(4); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(4000),
|
||||
bind(&LogicFixture::checkSeqNo, this, 1, 2, 4));
|
||||
[this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(4050),
|
||||
bind(&LogicFixture::checkSeqNo, this, 0, 2, 4));
|
||||
[this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4); });
|
||||
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(4500),
|
||||
bind(&LogicFixture::terminate, this));
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(4500), [this] { io.stop(); });
|
||||
|
||||
io.run();
|
||||
}
|
||||
@@ -259,47 +217,83 @@ BOOST_AUTO_TEST_CASE(ResetRecover)
|
||||
BOOST_AUTO_TEST_CASE(RecoverConflict)
|
||||
{
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(0),
|
||||
bind(&LogicFixture::createHandler, this, 0));
|
||||
[this] { handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(50),
|
||||
bind(&LogicFixture::createHandler, this, 1));
|
||||
[this] { handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[1]); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(100),
|
||||
bind(&LogicFixture::createHandler, this, 2));
|
||||
[this] { handler[2] = make_shared<Handler>(ref(*faces[2]), syncPrefix, userPrefix[2]); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(500),
|
||||
bind(&LogicFixture::updateSeqNo, this, 0, 1));
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(500), [this] { handler[0]->updateSeqNo(1); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(1400),
|
||||
bind(&LogicFixture::checkSeqNo, this, 1, 0, 1));
|
||||
[this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(1400),
|
||||
bind(&LogicFixture::checkSeqNo, this, 2, 0, 1));
|
||||
[this] { BOOST_CHECK_EQUAL(handler[2]->map[handler[0]->logic.getSessionName()], 1); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(1500),
|
||||
bind(&LogicFixture::updateSeqNo, this, 1, 2));
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(1500), [this] { handler[1]->updateSeqNo(2); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(1500),
|
||||
bind(&LogicFixture::updateSeqNo, this, 2, 4));
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(1500), [this] { handler[2]->updateSeqNo(4); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(2400),
|
||||
bind(&LogicFixture::checkSeqNo, this, 0, 1, 2));
|
||||
[this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 2); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(2450),
|
||||
bind(&LogicFixture::checkSeqNo, this, 0, 2, 4));
|
||||
[this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[2]->logic.getSessionName()], 4); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(2500),
|
||||
bind(&LogicFixture::checkSeqNo, this, 1, 2, 4));
|
||||
[this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[2]->logic.getSessionName()], 4); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(2550),
|
||||
bind(&LogicFixture::checkSeqNo, this, 2, 1, 2));
|
||||
[this] { BOOST_CHECK_EQUAL(handler[2]->map[handler[1]->logic.getSessionName()], 2); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(4500),
|
||||
bind(&LogicFixture::terminate, this));
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(4500), [this] { io.stop(); });
|
||||
|
||||
io.run();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(MultipleUserUnderOneLogic)
|
||||
{
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(0),
|
||||
[this] { handler[0] = make_shared<Handler>(ref(*faces[0]), syncPrefix, userPrefix[0]); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(50),
|
||||
[this] { handler[1] = make_shared<Handler>(ref(*faces[1]), syncPrefix, userPrefix[2]); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(100),
|
||||
[this] { handler[0]->logic.addUserNode(userPrefix[1]); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(500), [this] { handler[0]->updateSeqNo(1); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(1400),
|
||||
[this] { BOOST_CHECK_EQUAL(handler[1]->map[handler[0]->logic.getSessionName()], 1); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(1500),
|
||||
[this] { handler[0]->logic.updateSeqNo(2, userPrefix[1]); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(2400),
|
||||
[this] {
|
||||
Name sessionName = handler[0]->logic.getSessionName(userPrefix[1]);
|
||||
BOOST_CHECK_EQUAL(handler[1]->map[sessionName], 2);
|
||||
});
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(2500), [this] { handler[1]->updateSeqNo(4); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(3200),
|
||||
[this] { BOOST_CHECK_EQUAL(handler[0]->map[handler[1]->logic.getSessionName()], 4); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(3300),
|
||||
[this] { handler[0]->logic.removeUserNode(userPrefix[0]); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(4500),
|
||||
[this] { BOOST_CHECK_EQUAL(handler[1]->logic.getSessionNames().size(), 2); });
|
||||
|
||||
scheduler.scheduleEvent(ndn::time::milliseconds(5000), [this] { io.stop(); });
|
||||
|
||||
io.run();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
#include "logic.hpp"
|
||||
|
||||
#include "boost-test.hpp"
|
||||
|
||||
namespace chronosync {
|
||||
namespace test {
|
||||
|
||||
using std::vector;
|
||||
|
||||
|
||||
class Handler
|
||||
{
|
||||
public:
|
||||
Handler(ndn::Face& face,
|
||||
const Name& syncPrefix,
|
||||
const Name& userPrefix)
|
||||
: logic(face,
|
||||
syncPrefix,
|
||||
userPrefix,
|
||||
bind(&Handler::onUpdate, this, _1))
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
onUpdate(const vector<MissingDataInfo>& v)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
updateSeqNo(const SeqNo& seqNo)
|
||||
{
|
||||
logic.updateSeqNo(seqNo);
|
||||
}
|
||||
|
||||
void
|
||||
addUserNode(const Name& prefix)
|
||||
{
|
||||
logic.addUserNode(prefix);
|
||||
}
|
||||
|
||||
void
|
||||
removeUserNode(const Name& prefix)
|
||||
{
|
||||
logic.removeUserNode(prefix);
|
||||
}
|
||||
|
||||
|
||||
Logic logic;
|
||||
std::map<Name, SeqNo> map;
|
||||
};
|
||||
|
||||
class LogicFixture
|
||||
{
|
||||
public:
|
||||
|
||||
LogicFixture()
|
||||
: syncPrefix("/ndn/broadcast/sync")
|
||||
, scheduler(io)
|
||||
{
|
||||
syncPrefix.appendVersion();
|
||||
userPrefix[0] = Name("/user0");
|
||||
userPrefix[1] = Name("/user1");
|
||||
userPrefix[2] = Name("/user2");
|
||||
|
||||
face = make_shared<ndn::Face>(ref(io));
|
||||
}
|
||||
|
||||
Name syncPrefix;
|
||||
Name userPrefix[3];
|
||||
|
||||
boost::asio::io_service io;
|
||||
shared_ptr<ndn::Face> face;
|
||||
ndn::Scheduler scheduler;
|
||||
shared_ptr<Handler> handler;
|
||||
};
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(LogicTests, LogicFixture)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ThreeUserNode)
|
||||
{
|
||||
handler = make_shared<Handler>(ref(*face), syncPrefix, userPrefix[0]);
|
||||
handler->addUserNode(userPrefix[1]);
|
||||
handler->addUserNode(userPrefix[2]);
|
||||
handler->removeUserNode(userPrefix[0]);
|
||||
|
||||
handler->logic.setDefaultUserPrefix(userPrefix[1]);
|
||||
handler->updateSeqNo(1);
|
||||
BOOST_CHECK_EQUAL(handler->logic.getSeqNo(userPrefix[1]), 1);
|
||||
|
||||
handler->logic.updateSeqNo(2, userPrefix[2]);
|
||||
handler->logic.setDefaultUserPrefix(userPrefix[2]);
|
||||
|
||||
BOOST_CHECK_EQUAL(handler->logic.getSeqNo(), 2);
|
||||
|
||||
BOOST_REQUIRE_THROW(handler->logic.getSeqNo(userPrefix[0]), Logic::Error);
|
||||
BOOST_REQUIRE_THROW(handler->logic.getSessionName(userPrefix[0]), Logic::Error);
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
} // namespace test
|
||||
} // namespace chronosync
|
||||
Reference in new issue
Block a user