logic: allow manipulating multiple nodes in single logic
Change-Id: Iaa2a2b08e891d41c9aa71c13ffc531bef406b6d8
diff --git a/src/logic.cpp b/src/logic.cpp
index 4c3fc55..08ed60e 100644
--- a/src/logic.cpp
+++ b/src/logic.cpp
@@ -50,6 +50,7 @@
#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 @@
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 @@
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 @@
, m_resetInterestLifetime(resetInterestLifetime)
, m_syncInterestLifetime(syncInterestLifetime)
, m_syncReplyFreshness(syncReplyFreshness)
- , m_signingId(signingId)
+ , m_defaultSigningId(defaultSigningId)
, m_validator(validator)
{
#ifdef _DEBUG
@@ -97,6 +98,9 @@
_LOG_DEBUG_ID(">> Logic::Logic");
+ addUserNode(m_defaultUserPrefix, m_defaultSigningId);
+
+
m_syncReset = m_syncPrefix;
m_syncReset.append("reset");
@@ -106,7 +110,6 @@
bind(&Logic::onSyncInterest, this, _1, _2),
bind(&Logic::onSyncRegisterFailed, this, _1, _2));
- setUserPrefix(m_userPrefix);
_LOG_DEBUG_ID("<< Logic::Logic");
}
@@ -144,56 +147,132 @@
}
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 @@
// 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 @@
// 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 @@
// 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 @@
const Block& syncReplyBlock)
{
_LOG_DEBUG_ID(">> Logic::processSyncData");
-
DiffStatePtr commit = make_shared<DiffState>();
ndn::ConstBufferPtr previousRoot = m_state.getRootDigest();
@@ -411,7 +489,6 @@
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 @@
}
void
-Logic::satisfyPendingSyncInterests(ConstDiffStatePtr commit)
+Logic::satisfyPendingSyncInterests(const Name& updatedPrefix, ConstDiffStatePtr commit)
{
_LOG_DEBUG_ID(">> Logic::satisfyPendingSyncInterests");
try {
@@ -459,11 +536,10 @@
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 @@
}
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 @@
return;
m_isInReset = false;
- updateSeqNo(m_seqNo);
+ for (const auto& node : m_nodeList) {
+ updateSeqNo(node.second.seqNo, node.first);
+ }
_LOG_DEBUG_ID("<< Logic::cancelReset");
}
diff --git a/src/logic.hpp b/src/logic.hpp
index acca168..e8ea4f6 100644
--- a/src/logic.hpp
+++ b/src/logic.hpp
@@ -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 @@
* 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:
@@ -73,6 +81,17 @@
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;
static const time::milliseconds DEFAULT_RESET_INTEREST_LIFETIME;
@@ -83,8 +102,9 @@
* @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 @@
*/
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 @@
/**
* @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 @@
return m_state;
}
+
private:
/**
* @brief Callback to handle Sync Interest
@@ -304,7 +356,7 @@
* @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 @@
/// @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 @@
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 @@
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 @@
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;