blob: dbdfef763422d0fa8435351b013746ec51b06296 [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014-2018, Regents of the University of California.
*
* This file is part of NDN repo-ng (Next generation of NDN repository).
* See AUTHORS.md for complete list of repo-ng authors and contributors.
*
* repo-ng is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* repo-ng is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* repo-ng, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
*/
#include "read-handle.hpp"
#include "repo.hpp"
#include <ndn-cxx/util/logger.hpp>
namespace repo {
NDN_LOG_INIT(repo.ReadHandle);
ReadHandle::ReadHandle(Face& face, RepoStorage& storageHandle, size_t prefixSubsetLength)
: m_prefixSubsetLength(prefixSubsetLength)
, m_face(face)
, m_storageHandle(storageHandle)
{
connectAutoListen();
}
void
ReadHandle::connectAutoListen()
{
// Connect a RepoStorage's signals to the read handle
if (m_prefixSubsetLength != RepoConfig::DISABLED_SUBSET_LENGTH) {
afterDataInsertionConnection = m_storageHandle.afterDataInsertion.connect(
[this] (const Name& prefix) {
onDataInserted(prefix);
});
afterDataDeletionConnection = m_storageHandle.afterDataDeletion.connect(
[this] (const Name& prefix) {
onDataDeleted(prefix);
});
}
}
void
ReadHandle::onInterest(const Name& prefix, const Interest& interest)
{
NDN_LOG_DEBUG("Received Interest " << interest.getName());
std::shared_ptr<ndn::Data> data = m_storageHandle.readData(interest);
if (data != nullptr) {
NDN_LOG_DEBUG("Put Data: " << *data);
m_face.put(*data);
}
else {
NDN_LOG_DEBUG("No data for " << interest.getName());
}
}
void
ReadHandle::onRegisterFailed(const Name& prefix, const std::string& reason)
{
NDN_LOG_ERROR("ERROR: Failed to register prefix in local hub's daemon");
m_face.shutdown();
}
void
ReadHandle::listen(const Name& prefix)
{
ndn::InterestFilter filter(prefix);
m_face.setInterestFilter(filter,
std::bind(&ReadHandle::onInterest, this, _1, _2),
std::bind(&ReadHandle::onRegisterFailed, this, _1, _2));
}
void
ReadHandle::onDataDeleted(const Name& name)
{
// We add one here to account for the implicit digest at the end,
// which is what we get from the underlying storage when deleting.
Name prefix = name.getPrefix(-(m_prefixSubsetLength + 1));
auto check = m_insertedDataPrefixes.find(prefix);
if (check != m_insertedDataPrefixes.end()) {
if (--(check->second.useCount) <= 0) {
m_face.unsetInterestFilter(check->second.prefixId);
m_insertedDataPrefixes.erase(prefix);
}
}
}
void
ReadHandle::onDataInserted(const Name& name)
{
// Note: We want to save the prefix that we register exactly, not the
// name that provoked the registration
Name prefixToRegister = name.getPrefix(-m_prefixSubsetLength);
ndn::InterestFilter filter(prefixToRegister);
auto check = m_insertedDataPrefixes.find(prefixToRegister);
if (check == m_insertedDataPrefixes.end()) {
// Because of stack lifetime problems, we assume here that the
// prefix registration will be successful, and we add the registered
// prefix to our list. This is because, if we fail, we shut
// everything down, anyway. If registration failures are ever
// considered to be recoverable, we would need to make this
// atomic.
const ndn::RegisteredPrefixId* prefixId = m_face.setInterestFilter(filter,
[this] (const ndn::InterestFilter& filter, const Interest& interest) {
// Implicit conversion to Name of filter
onInterest(filter, interest);
},
[] (const Name&) {},
[this] (const Name& prefix, const std::string& reason) {
onRegisterFailed(prefix, reason);
});
RegisteredDataPrefix registeredPrefix{prefixId, 1};
// Newly registered prefix
m_insertedDataPrefixes.emplace(std::make_pair(prefixToRegister, registeredPrefix));
}
else {
check->second.useCount++;
}
}
} // namespace repo