blob: 0e1da2c98583727ae4de99f4611ef952fde22aeb [file] [log] [blame]
Weiqi Shi68f2cf62014-08-26 12:35:45 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento49f3a5f2017-09-23 01:36:33 -04002/*
Davide Pesavento9c0bd8d2022-03-14 16:48:12 -04003 * Copyright (c) 2014-2022, Regents of the University of California.
Weiqi Shi68f2cf62014-08-26 12:35:45 -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
Alexander Afanasyev42290b22017-03-09 12:58:29 -080017 * repo-ng, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Weiqi Shi68f2cf62014-08-26 12:35:45 -070018 */
19
20/**
Davide Pesavento8891c832019-03-20 23:20:35 -040021 * @file This file demonstrates how to generate data to be stored in a repo using
22 * the repo watch protocol and repo insertion protocol.
23 *
24 * The details of the protocols can be found here:
Alexander Afanasyev42290b22017-03-09 12:58:29 -080025 * <https://redmine.named-data.net/projects/repo-ng/wiki/Watched_Prefix_Insertion_Protocol>
26 * <https://redmine.named-data.net/projects/repo-ng/wiki/Basic_Repo_Insertion_Protocol>
Weiqi Shi68f2cf62014-08-26 12:35:45 -070027 *
28 * This file is used for debugging purpose. There are two modes for users to assign
29 * names for the data.
30 * 1)read the data name from a specific file
31 * 2)input a prefix and a random version number will be added automatically
32 * Users need to run nfd and repo-ng and set up specific repo protocols mentioned
33 * above before running this program.
34 * The description of command parameter can be found in the function usage().
35 */
36
Davide Pesaventod45e62b2018-01-01 23:33:18 -050037#include <boost/asio/io_service.hpp>
Weiqi Shi68f2cf62014-08-26 12:35:45 -070038#include <boost/lexical_cast.hpp>
Davide Pesavento8891c832019-03-20 23:20:35 -040039
40#include <ndn-cxx/data.hpp>
41#include <ndn-cxx/face.hpp>
42#include <ndn-cxx/name.hpp>
43#include <ndn-cxx/util/random.hpp>
44#include <ndn-cxx/util/scheduler.hpp>
45#include <ndn-cxx/util/time.hpp>
46
Davide Pesavento49f3a5f2017-09-23 01:36:33 -040047#include <fstream>
Weiqi Shi68f2cf62014-08-26 12:35:45 -070048#include <iostream>
Davide Pesavento49f3a5f2017-09-23 01:36:33 -040049#include <random>
50#include <string>
Weiqi Shi68f2cf62014-08-26 12:35:45 -070051
52namespace repo {
53
Davide Pesavento49f3a5f2017-09-23 01:36:33 -040054using ndn::time::milliseconds;
Weiqi Shi68f2cf62014-08-26 12:35:45 -070055
Davide Pesavento8891c832019-03-20 23:20:35 -040056const milliseconds DEFAULT_TIME_INTERVAL(2000);
Weiqi Shi68f2cf62014-08-26 12:35:45 -070057
Davide Pesavento49f3a5f2017-09-23 01:36:33 -040058enum Mode {
Weiqi Shi68f2cf62014-08-26 12:35:45 -070059 AUTO,
60 READFILE
61};
62
63class Publisher
64{
65public:
66 class Error : public std::runtime_error
67 {
68 public:
Davide Pesavento8891c832019-03-20 23:20:35 -040069 using std::runtime_error::runtime_error;
Weiqi Shi68f2cf62014-08-26 12:35:45 -070070 };
71
72public:
73 Publisher()
74 : mode(AUTO)
Davide Pesavento8891c832019-03-20 23:20:35 -040075 , dataPrefix("/example/data")
Weiqi Shi68f2cf62014-08-26 12:35:45 -070076 , timeInterval(DEFAULT_TIME_INTERVAL)
77 , duration(0)
78 , m_scheduler(m_face.getIoService())
Davide Pesavento49f3a5f2017-09-23 01:36:33 -040079 , m_randomDist(200, 1000)
Weiqi Shi68f2cf62014-08-26 12:35:45 -070080 {
81 }
82
83 void
84 run();
85
86 void
87 autoGenerate();
88
89 void
90 generateFromFile();
91
Davide Pesavento8891c832019-03-20 23:20:35 -040092 static std::shared_ptr<ndn::Data>
Weiqi Shi68f2cf62014-08-26 12:35:45 -070093 createData(const ndn::Name& name);
Davide Pesavento49f3a5f2017-09-23 01:36:33 -040094
Weiqi Shi68f2cf62014-08-26 12:35:45 -070095public:
96 std::ifstream insertStream;
97 Mode mode;
Davide Pesavento8891c832019-03-20 23:20:35 -040098 ndn::Name dataPrefix;
Weiqi Shi68f2cf62014-08-26 12:35:45 -070099 milliseconds timeInterval;
100 milliseconds duration;
101
102private:
103 ndn::Face m_face;
104 ndn::Scheduler m_scheduler;
Davide Pesavento8891c832019-03-20 23:20:35 -0400105 std::uniform_int_distribution<> m_randomDist;
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700106};
107
108void
109Publisher::run()
110{
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700111 if (mode == AUTO) {
Davide Pesavento8891c832019-03-20 23:20:35 -0400112 m_scheduler.schedule(timeInterval, [this] { autoGenerate(); });
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700113 }
114 else {
Davide Pesavento8891c832019-03-20 23:20:35 -0400115 m_scheduler.schedule(timeInterval, [this] { generateFromFile(); });
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700116 }
117 m_face.processEvents(duration);
118}
119
120void
121Publisher::autoGenerate()
122{
Davide Pesavento8891c832019-03-20 23:20:35 -0400123 ndn::Name name = dataPrefix;
124 name.appendNumber(m_randomDist(ndn::random::getRandomNumberEngine()));
125 auto data = createData(name);
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700126 m_face.put(*data);
Davide Pesavento8891c832019-03-20 23:20:35 -0400127
128 m_scheduler.schedule(timeInterval, [this] { autoGenerate(); });
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700129}
130
131void
132Publisher::generateFromFile()
133{
134 if (insertStream.eof()) {
135 m_face.getIoService().stop();
136 return;
Davide Pesavento8891c832019-03-20 23:20:35 -0400137 }
138
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700139 std::string name;
140 getline(insertStream, name);
Davide Pesavento9c0bd8d2022-03-14 16:48:12 -0400141 auto data = createData(name);
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700142 m_face.put(*data);
Davide Pesavento8891c832019-03-20 23:20:35 -0400143
144 m_scheduler.schedule(timeInterval, [this] { generateFromFile(); });
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700145}
146
Davide Pesavento8891c832019-03-20 23:20:35 -0400147std::shared_ptr<ndn::Data>
148Publisher::createData(const ndn::Name& name)
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700149{
150 static ndn::KeyChain keyChain;
Davide Pesavento9c0bd8d2022-03-14 16:48:12 -0400151 static const std::vector<uint8_t> content(1500, '-');
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700152
Davide Pesavento9c0bd8d2022-03-14 16:48:12 -0400153 auto data = std::make_shared<ndn::Data>(name);
154 data->setContent(content);
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700155 keyChain.sign(*data);
156 return data;
157}
158
159static void
160usage()
161{
162 std::cerr
163 << " Publisher [-d dataPrefix] [-f filename] [-s duration time] [-t generate time interval] \n"
164 << " -d: specify the data prefix publisher generate\n"
165 << " -f: specify filename that publish would read from\n"
166 << " -s: specify the time duration of generate data\n"
167 << " -t: specify the time interval between two data generated\n"
168 << std::endl;
169 exit(1);
170}
171
Davide Pesavento49f3a5f2017-09-23 01:36:33 -0400172static int
Davide Pesavento8891c832019-03-20 23:20:35 -0400173main(int argc, char* argv[])
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700174{
175 Publisher generator;
176 bool isAuto = false;
177 bool isRead = false;
178 int opt;
179 while ((opt = getopt(argc, argv, "d:f:s:t:")) != -1) {
180 switch (opt) {
181 case 'd':
182 {
Davide Pesavento8891c832019-03-20 23:20:35 -0400183 generator.dataPrefix = ndn::Name(std::string(optarg));
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700184 generator.mode = AUTO;
185 isAuto = true;
186 }
187 break;
188 case 'f':
189 {
190 isRead = true;
191 generator.mode = READFILE;
192 std::string str = std::string(optarg);
193 generator.insertStream.open(str.c_str());
194 if (!generator.insertStream.is_open()) {
195 std::cerr << "ERROR: cannot open " << std::string(optarg) << std::endl;
196 return 1;
197 }
198 }
199 break;
200 case 's':
201 try {
202 generator.duration = milliseconds(boost::lexical_cast<uint64_t>(optarg));
203 }
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800204 catch (const boost::bad_lexical_cast&) {
Davide Pesavento9c0bd8d2022-03-14 16:48:12 -0400205 std::cerr << "-s option should be an integer" << std::endl;
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700206 return 1;
207 }
208 break;
209 case 't':
210 try {
211 generator.timeInterval = milliseconds(boost::lexical_cast<uint64_t>(optarg));
212 }
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800213 catch (const boost::bad_lexical_cast&) {
Davide Pesavento9c0bd8d2022-03-14 16:48:12 -0400214 std::cerr << "-t option should be an integer" << std::endl;
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700215 return 1;
216 }
217 break;
218 default:
219 usage();
220 break;
221 }
222 }
223
224 argc -= optind;
225 argv += optind;
226
227 if (argc != 0)
228 usage();
229
230 if (isAuto && isRead)
231 usage();
232
233 generator.run();
234 return 0;
235}
236
237} // namespace repo
238
239int
Davide Pesavento8891c832019-03-20 23:20:35 -0400240main(int argc, char* argv[])
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700241{
242 try {
243 return repo::main(argc, argv);
244 }
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800245 catch (const std::exception& e) {
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700246 std::cerr << "ERROR: " << e.what() << std::endl;
247 return 2;
248 }
249}