blob: acc83bd6d4a7450c664e9b7f43e49d0412367b3e [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 Pesaventod8521aa2023-09-17 14:21:27 -04003 * Copyright (c) 2014-2023, 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());
Davide Pesavento11904062022-04-14 22:33:28 -040037 if (!fin.is_open())
38 NDN_THROW(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 }
Davide Pesavento11904062022-04-14 22:33:28 -040045 catch (const ptree_error&) {
46 NDN_THROW_NESTED(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
Davide Pesavento11904062022-04-14 22:33:28 -040061 NDN_THROW(Repo::Error("Unrecognized '" + section.first + "' option in 'data' section in "
62 "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
Davide Pesavento11904062022-04-14 22:33:28 -040070 NDN_THROW(Repo::Error("Unrecognized '" + section.first + "' option in 'command' section in "
71 "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
Davide Pesavento11904062022-04-14 22:33:28 -040088 NDN_THROW(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") {
Davide Pesavento11904062022-04-14 22:33:28 -040097 NDN_THROW(Repo::Error("Only 'sqlite' storage method is supported"));
Alexander Afanasyev42290b22017-03-09 12:58:29 -080098 }
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
Davide Pesaventod8521aa2023-09-17 14:21:27 -0400109Repo::Repo(boost::asio::io_context& io, const RepoConfig& config)
Shuo Chen478204c2014-03-18 18:27:04 -0700110 : m_config(config)
Davide Pesaventod8521aa2023-09-17 14:21:27 -0400111 , m_scheduler(io)
112 , m_face(io)
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)
Davide Pesaventod8521aa2023-09-17 14:21:27 -0400120 , m_tcpBulkInsertHandle(io, m_storageHandle)
Shuo Chen478204c2014-03-18 18:27:04 -0700121{
Junxiao Shi047a6fb2017-06-08 16:16:05 +0000122 this->enableValidation();
Alexander Afanasyev5c16cc22019-04-02 14:17:12 -0400123 m_storageHandle.notifyAboutExistingData();
Shuo Chen478204c2014-03-18 18:27:04 -0700124}
125
126void
Shuo Chena12f5282014-08-01 15:18:30 +0800127Repo::initializeStorage()
128{
129 // Rebuild storage if storage checkpoin exists
Davide Pesavento11904062022-04-14 22:33:28 -0400130 auto start = time::steady_clock::now();
131 auto end = time::steady_clock::now();
132 auto cost = time::duration_cast<time::milliseconds>(end - start);
133 NDN_LOG_DEBUG("initialize storage cost: " << cost);
Shuo Chena12f5282014-08-01 15:18:30 +0800134}
135
136void
Shuo Chen478204c2014-03-18 18:27:04 -0700137Repo::enableListening()
138{
Junxiao Shi2b7b8312017-06-16 03:43:24 +0000139 for (const ndn::Name& dataPrefix : m_config.dataPrefixes) {
140 // ReadHandle performs prefix registration internally.
141 m_readHandle.listen(dataPrefix);
142 }
Junxiao Shi2b7b8312017-06-16 03:43:24 +0000143 for (const ndn::Name& cmdPrefix : m_config.repoPrefixes) {
144 m_face.registerPrefix(cmdPrefix, nullptr,
145 [] (const Name& cmdPrefix, const std::string& reason) {
weijia yuan3aa8d2b2018-03-06 15:35:57 -0800146 NDN_LOG_DEBUG("Command prefix " << cmdPrefix << " registration error: " << reason);
Davide Pesavento11904062022-04-14 22:33:28 -0400147 NDN_THROW(Error("Command prefix registration failed"));
Junxiao Shi2b7b8312017-06-16 03:43:24 +0000148 });
Shuo Chen478204c2014-03-18 18:27:04 -0700149
weijia yuan82cf9142018-10-21 12:25:02 -0700150 m_dispatcher.addTopPrefix(cmdPrefix);
Junxiao Shi2b7b8312017-06-16 03:43:24 +0000151 }
152
153 for (const auto& ep : m_config.tcpBulkInsertEndpoints) {
154 m_tcpBulkInsertHandle.listen(ep.first, ep.second);
155 }
Shuo Chen478204c2014-03-18 18:27:04 -0700156}
157
Shuo Chen028dcd32014-06-21 16:36:44 +0800158void
159Repo::enableValidation()
160{
Alexander Afanasyevc0e26582017-08-13 21:16:49 -0400161 m_validator.load(m_config.validatorNode, m_config.repoConfigPath);
Shuo Chen028dcd32014-06-21 16:36:44 +0800162}
163
Shuo Chen478204c2014-03-18 18:27:04 -0700164} // namespace repo