blob: 2bdc833e55851f564605c2e825b77ca873aa4c04 [file] [log] [blame]
Shuo Chen478204c2014-03-18 18:27:04 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Alexander Afanasyevc0e26582017-08-13 21:16:49 -04002/*
Davide Pesaventoe18d3682019-01-24 22:10:30 -05003 * Copyright (c) 2014-2019, Regents of the University of California.
Alexander Afanasyeve1e6f2a2014-04-25 11:28:12 -07004 *
5 * This file is part of NDN repo-ng (Next generation of NDN repository).
6 * See AUTHORS.md for complete list of repo-ng authors and contributors.
7 *
8 * repo-ng is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation,
10 * either version 3 of the License, or (at your option) any later version.
11 *
12 * repo-ng is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * repo-ng, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Shuo Chen478204c2014-03-18 18:27:04 -070018 */
19
20#include "repo.hpp"
Weiqi Shif0330d52014-07-09 10:54:27 -070021#include "storage/sqlite-storage.hpp"
Wentao Shanga8f3c402014-10-30 14:03:27 -070022
weijia yuan3aa8d2b2018-03-06 15:35:57 -080023#include <ndn-cxx/util/logger.hpp>
24
Shuo Chen478204c2014-03-18 18:27:04 -070025namespace repo {
26
Davide Pesaventoe18d3682019-01-24 22:10:30 -050027NDN_LOG_INIT(repo.Repo);
weijia yuan3aa8d2b2018-03-06 15:35:57 -080028
Shuo Chen478204c2014-03-18 18:27:04 -070029RepoConfig
30parseConfig(const std::string& configPath)
31{
32 if (configPath.empty()) {
weijia yuan3aa8d2b2018-03-06 15:35:57 -080033 NDN_LOG_DEBUG("configuration file path is empty");
Shuo Chen478204c2014-03-18 18:27:04 -070034 }
35
36 std::ifstream fin(configPath.c_str());
Nick Gordon190e4dc2017-10-04 16:54:10 -050037 if (!fin.is_open())
weijia yuan3aa8d2b2018-03-06 15:35:57 -080038 BOOST_THROW_EXCEPTION(Repo::Error("failed to open configuration file '" + configPath + "'"));
Shuo Chen478204c2014-03-18 18:27:04 -070039
40 using namespace boost::property_tree;
41 ptree propertyTree;
42 try {
43 read_info(fin, propertyTree);
44 }
Alexander Afanasyev42290b22017-03-09 12:58:29 -080045 catch (const ptree_error& e) {
weijia yuan3aa8d2b2018-03-06 15:35:57 -080046 BOOST_THROW_EXCEPTION(Repo::Error("failed to read configuration file '" + configPath + "'"));
Shuo Chen478204c2014-03-18 18:27:04 -070047 }
48
49 ptree repoConf = propertyTree.get_child("repo");
50
51 RepoConfig repoConfig;
Shuo Chen028dcd32014-06-21 16:36:44 +080052 repoConfig.repoConfigPath = configPath;
Shuo Chen478204c2014-03-18 18:27:04 -070053
54 ptree dataConf = repoConf.get_child("data");
Alexander Afanasyev81203b92017-11-09 13:53:56 -050055 for (const auto& section : dataConf) {
Nick Gordon190e4dc2017-10-04 16:54:10 -050056 if (section.first == "prefix")
57 repoConfig.dataPrefixes.push_back(Name(section.second.get_value<std::string>()));
58 else if (section.first == "registration-subset")
59 repoConfig.registrationSubset = section.second.get_value<int>();
Shuo Chen478204c2014-03-18 18:27:04 -070060 else
Nick Gordon190e4dc2017-10-04 16:54:10 -050061 BOOST_THROW_EXCEPTION(Repo::Error("Unrecognized '" + section.first + "' option in 'data' section in "
Alexander Afanasyev42290b22017-03-09 12:58:29 -080062 "configuration file '"+ configPath +"'"));
Shuo Chen478204c2014-03-18 18:27:04 -070063 }
64
65 ptree commandConf = repoConf.get_child("command");
Alexander Afanasyev81203b92017-11-09 13:53:56 -050066 for (const auto& section : commandConf) {
Nick Gordon190e4dc2017-10-04 16:54:10 -050067 if (section.first == "prefix")
68 repoConfig.repoPrefixes.push_back(Name(section.second.get_value<std::string>()));
Shuo Chen478204c2014-03-18 18:27:04 -070069 else
Nick Gordon190e4dc2017-10-04 16:54:10 -050070 BOOST_THROW_EXCEPTION(Repo::Error("Unrecognized '" + section.first + "' option in 'command' section in "
Alexander Afanasyev42290b22017-03-09 12:58:29 -080071 "configuration file '"+ configPath +"'"));
Shuo Chen478204c2014-03-18 18:27:04 -070072 }
73
Alexander Afanasyev81203b92017-11-09 13:53:56 -050074 auto tcpBulkInsert = repoConf.get_child_optional("tcp_bulk_insert");
Shuo Chen478204c2014-03-18 18:27:04 -070075 bool isTcpBulkEnabled = false;
76 std::string host = "localhost";
77 std::string port = "7376";
Alexander Afanasyev81203b92017-11-09 13:53:56 -050078 if (tcpBulkInsert) {
79 for (const auto& section : *tcpBulkInsert) {
80 isTcpBulkEnabled = true;
Alexander Afanasyev81203b92017-11-09 13:53:56 -050081 if (section.first == "host") {
82 host = section.second.get_value<std::string>();
83 }
84 else if (section.first == "port") {
85 port = section.second.get_value<std::string>();
86 }
87 else
88 BOOST_THROW_EXCEPTION(Repo::Error("Unrecognized '" + section.first + "' option in 'tcp_bulk_insert' section in "
89 "configuration file '"+ configPath +"'"));
Shuo Chen478204c2014-03-18 18:27:04 -070090 }
Shuo Chen478204c2014-03-18 18:27:04 -070091 }
92 if (isTcpBulkEnabled) {
93 repoConfig.tcpBulkInsertEndpoints.push_back(std::make_pair(host, port));
94 }
95
Alexander Afanasyev42290b22017-03-09 12:58:29 -080096 if (repoConf.get<std::string>("storage.method") != "sqlite") {
97 BOOST_THROW_EXCEPTION(Repo::Error("Only 'sqlite' storage method is supported"));
98 }
Shuo Chen478204c2014-03-18 18:27:04 -070099
100 repoConfig.dbPath = repoConf.get<std::string>("storage.path");
101
102 repoConfig.validatorNode = repoConf.get_child("validator");
Weiqi Shif0330d52014-07-09 10:54:27 -0700103
Shuo Chen6e818122015-05-04 10:40:03 +0800104 repoConfig.nMaxPackets = repoConf.get<uint64_t>("storage.max-packets");
Weiqi Shif0330d52014-07-09 10:54:27 -0700105
Shuo Chen478204c2014-03-18 18:27:04 -0700106 return repoConfig;
107}
108
Shuo Chen478204c2014-03-18 18:27:04 -0700109Repo::Repo(boost::asio::io_service& ioService, const RepoConfig& config)
110 : m_config(config)
111 , m_scheduler(ioService)
Wentao Shang91fb4f22014-05-20 10:55:22 -0700112 , m_face(ioService)
weijia yuan82cf9142018-10-21 12:25:02 -0700113 , m_dispatcher(m_face, m_keyChain)
Wentao Shanga8f3c402014-10-30 14:03:27 -0700114 , m_store(std::make_shared<SqliteStorage>(config.dbPath))
weijia yuan3aa8d2b2018-03-06 15:35:57 -0800115 , m_storageHandle(*m_store)
Alexander Afanasyevc0e26582017-08-13 21:16:49 -0400116 , m_validator(m_face)
weijia yuan82cf9142018-10-21 12:25:02 -0700117 , m_readHandle(m_face, m_storageHandle, m_config.registrationSubset)
118 , m_writeHandle(m_face, m_storageHandle, m_dispatcher, m_scheduler, m_validator)
weijia yuan82cf9142018-10-21 12:25:02 -0700119 , m_deleteHandle(m_face, m_storageHandle, m_dispatcher, m_scheduler, m_validator)
Weiqi Shif0330d52014-07-09 10:54:27 -0700120 , m_tcpBulkInsertHandle(ioService, m_storageHandle)
Shuo Chen478204c2014-03-18 18:27:04 -0700121{
Junxiao Shi047a6fb2017-06-08 16:16:05 +0000122 this->enableValidation();
Shuo Chen478204c2014-03-18 18:27:04 -0700123}
124
125void
Shuo Chena12f5282014-08-01 15:18:30 +0800126Repo::initializeStorage()
127{
128 // Rebuild storage if storage checkpoin exists
129 ndn::time::steady_clock::TimePoint start = ndn::time::steady_clock::now();
Shuo Chena12f5282014-08-01 15:18:30 +0800130 ndn::time::steady_clock::TimePoint end = ndn::time::steady_clock::now();
131 ndn::time::milliseconds cost = ndn::time::duration_cast<ndn::time::milliseconds>(end - start);
weijia yuan3aa8d2b2018-03-06 15:35:57 -0800132 NDN_LOG_DEBUG("initialize storage cost: " << cost << "ms");
Shuo Chena12f5282014-08-01 15:18:30 +0800133}
134
135void
Shuo Chen478204c2014-03-18 18:27:04 -0700136Repo::enableListening()
137{
Junxiao Shi2b7b8312017-06-16 03:43:24 +0000138 for (const ndn::Name& dataPrefix : m_config.dataPrefixes) {
139 // ReadHandle performs prefix registration internally.
140 m_readHandle.listen(dataPrefix);
141 }
Junxiao Shi2b7b8312017-06-16 03:43:24 +0000142 for (const ndn::Name& cmdPrefix : m_config.repoPrefixes) {
143 m_face.registerPrefix(cmdPrefix, nullptr,
144 [] (const Name& cmdPrefix, const std::string& reason) {
weijia yuan3aa8d2b2018-03-06 15:35:57 -0800145 NDN_LOG_DEBUG("Command prefix " << cmdPrefix << " registration error: " << reason);
Junxiao Shi2b7b8312017-06-16 03:43:24 +0000146 BOOST_THROW_EXCEPTION(Error("Command prefix registration failed"));
147 });
Shuo Chen478204c2014-03-18 18:27:04 -0700148
weijia yuan82cf9142018-10-21 12:25:02 -0700149 m_dispatcher.addTopPrefix(cmdPrefix);
Junxiao Shi2b7b8312017-06-16 03:43:24 +0000150 }
151
152 for (const auto& ep : m_config.tcpBulkInsertEndpoints) {
153 m_tcpBulkInsertHandle.listen(ep.first, ep.second);
154 }
Shuo Chen478204c2014-03-18 18:27:04 -0700155}
156
Shuo Chen028dcd32014-06-21 16:36:44 +0800157void
158Repo::enableValidation()
159{
Alexander Afanasyevc0e26582017-08-13 21:16:49 -0400160 m_validator.load(m_config.validatorNode, m_config.repoConfigPath);
Shuo Chen028dcd32014-06-21 16:36:44 +0800161}
162
Shuo Chen478204c2014-03-18 18:27:04 -0700163} // namespace repo