blob: f81ab03873424090fde301d95a21d530950c2727 [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 Pesaventod45e62b2018-01-01 23:33:18 -05003 * Copyright (c) 2014-2018, 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/**
21 * This file demonstrates how to generate data to be stored in repo with repo watch
22 * protocol and repo insert protocol.
23 * The details of the protocols can be find here
Alexander Afanasyev42290b22017-03-09 12:58:29 -080024 * <https://redmine.named-data.net/projects/repo-ng/wiki/Watched_Prefix_Insertion_Protocol>
25 * <https://redmine.named-data.net/projects/repo-ng/wiki/Basic_Repo_Insertion_Protocol>
Weiqi Shi68f2cf62014-08-26 12:35:45 -070026 *
27 * This file is used for debugging purpose. There are two modes for users to assign
28 * names for the data.
29 * 1)read the data name from a specific file
30 * 2)input a prefix and a random version number will be added automatically
31 * Users need to run nfd and repo-ng and set up specific repo protocols mentioned
32 * above before running this program.
33 * The description of command parameter can be found in the function usage().
34 */
35
36#include "../src/common.hpp"
Davide Pesavento49f3a5f2017-09-23 01:36:33 -040037
Davide Pesaventod45e62b2018-01-01 23:33:18 -050038#include <boost/asio/io_service.hpp>
Weiqi Shi68f2cf62014-08-26 12:35:45 -070039#include <boost/lexical_cast.hpp>
Davide Pesavento49f3a5f2017-09-23 01:36:33 -040040#include <fstream>
Weiqi Shi68f2cf62014-08-26 12:35:45 -070041#include <iostream>
Davide Pesavento49f3a5f2017-09-23 01:36:33 -040042#include <random>
43#include <string>
Weiqi Shi68f2cf62014-08-26 12:35:45 -070044
45namespace repo {
46
Davide Pesavento49f3a5f2017-09-23 01:36:33 -040047using ndn::time::milliseconds;
Weiqi Shi68f2cf62014-08-26 12:35:45 -070048
49static const milliseconds DEFAULT_TIME_INTERVAL(2000);
50
Davide Pesavento49f3a5f2017-09-23 01:36:33 -040051enum Mode {
Weiqi Shi68f2cf62014-08-26 12:35:45 -070052 AUTO,
53 READFILE
54};
55
56class Publisher
57{
58public:
59 class Error : public std::runtime_error
60 {
61 public:
62 explicit
63 Error(const std::string& what)
64 : std::runtime_error(what)
65 {
66 }
67 };
68
69public:
70 Publisher()
71 : mode(AUTO)
72 , dataPrefix(Name("/example/data"))
73 , timeInterval(DEFAULT_TIME_INTERVAL)
74 , duration(0)
75 , m_scheduler(m_face.getIoService())
Davide Pesavento49f3a5f2017-09-23 01:36:33 -040076 , m_randomEngine(std::random_device{}())
77 , m_randomDist(200, 1000)
78 , m_range([this] { return m_randomDist(m_randomEngine); })
Weiqi Shi68f2cf62014-08-26 12:35:45 -070079 {
80 }
81
82 void
83 run();
84
85 void
86 autoGenerate();
87
88 void
89 generateFromFile();
90
Alexander Afanasyev42290b22017-03-09 12:58:29 -080091 std::shared_ptr<ndn::Data>
Weiqi Shi68f2cf62014-08-26 12:35:45 -070092 createData(const ndn::Name& name);
Davide Pesavento49f3a5f2017-09-23 01:36:33 -040093
Weiqi Shi68f2cf62014-08-26 12:35:45 -070094public:
95 std::ifstream insertStream;
96 Mode mode;
97 Name dataPrefix;
98 milliseconds timeInterval;
99 milliseconds duration;
100
101private:
102 ndn::Face m_face;
103 ndn::Scheduler m_scheduler;
Davide Pesavento49f3a5f2017-09-23 01:36:33 -0400104 std::mt19937 m_randomEngine;
105 std::uniform_int_distribution<unsigned int> m_randomDist;
106 std::function<unsigned int(void)> m_range;
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700107};
108
109void
110Publisher::run()
111{
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700112 if (mode == AUTO) {
weijia yuan3aa8d2b2018-03-06 15:35:57 -0800113 m_scheduler.scheduleEvent(timeInterval, std::bind(&Publisher::autoGenerate, this));
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700114 }
115 else {
weijia yuan3aa8d2b2018-03-06 15:35:57 -0800116 m_scheduler.scheduleEvent(timeInterval, std::bind(&Publisher::generateFromFile, this));
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700117 }
118 m_face.processEvents(duration);
119}
120
121void
122Publisher::autoGenerate()
123{
124 Name name = dataPrefix;
125 name.appendNumber(m_range());
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800126 std::shared_ptr<Data> data = createData(name);
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700127 m_face.put(*data);
weijia yuan3aa8d2b2018-03-06 15:35:57 -0800128 m_scheduler.scheduleEvent(timeInterval, std::bind(&Publisher::autoGenerate, this));
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700129}
130
131void
132Publisher::generateFromFile()
133{
134 if (insertStream.eof()) {
135 m_face.getIoService().stop();
136 return;
137 }
138 std::string name;
139 getline(insertStream, name);
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800140 std::shared_ptr<Data> data = createData(Name(name));
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700141 m_face.put(*data);
weijia yuan3aa8d2b2018-03-06 15:35:57 -0800142 m_scheduler.scheduleEvent(timeInterval, std::bind(&Publisher::generateFromFile, this));
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700143}
144
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800145std::shared_ptr<Data>
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700146Publisher::createData(const Name& name)
147{
148 static ndn::KeyChain keyChain;
149 static std::vector<uint8_t> content(1500, '-');
150
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800151 std::shared_ptr<ndn::Data> data = std::make_shared<Data>();
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700152 data->setName(name);
153 data->setContent(&content[0], content.size());
154 keyChain.sign(*data);
155 return data;
156}
157
158static void
159usage()
160{
161 std::cerr
162 << " Publisher [-d dataPrefix] [-f filename] [-s duration time] [-t generate time interval] \n"
163 << " -d: specify the data prefix publisher generate\n"
164 << " -f: specify filename that publish would read from\n"
165 << " -s: specify the time duration of generate data\n"
166 << " -t: specify the time interval between two data generated\n"
167 << std::endl;
168 exit(1);
169}
170
Davide Pesavento49f3a5f2017-09-23 01:36:33 -0400171static int
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700172main(int argc, char** argv)
173{
174 Publisher generator;
175 bool isAuto = false;
176 bool isRead = false;
177 int opt;
178 while ((opt = getopt(argc, argv, "d:f:s:t:")) != -1) {
179 switch (opt) {
180 case 'd':
181 {
182 generator.dataPrefix = Name(std::string(optarg));
183 generator.mode = AUTO;
184 isAuto = true;
185 }
186 break;
187 case 'f':
188 {
189 isRead = true;
190 generator.mode = READFILE;
191 std::string str = std::string(optarg);
192 generator.insertStream.open(str.c_str());
193 if (!generator.insertStream.is_open()) {
194 std::cerr << "ERROR: cannot open " << std::string(optarg) << std::endl;
195 return 1;
196 }
197 }
198 break;
199 case 's':
200 try {
201 generator.duration = milliseconds(boost::lexical_cast<uint64_t>(optarg));
202 }
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800203 catch (const boost::bad_lexical_cast&) {
weijia yuan3aa8d2b2018-03-06 15:35:57 -0800204 std::cerr << "-s option should be an integer" << std::endl;;
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700205 return 1;
206 }
207 break;
208 case 't':
209 try {
210 generator.timeInterval = milliseconds(boost::lexical_cast<uint64_t>(optarg));
211 }
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800212 catch (const boost::bad_lexical_cast&) {
weijia yuan3aa8d2b2018-03-06 15:35:57 -0800213 std::cerr << "-t option should be an integer" << std::endl;;
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700214 return 1;
215 }
216 break;
217 default:
218 usage();
219 break;
220 }
221 }
222
223 argc -= optind;
224 argv += optind;
225
226 if (argc != 0)
227 usage();
228
229 if (isAuto && isRead)
230 usage();
231
232 generator.run();
233 return 0;
234}
235
236} // namespace repo
237
238int
239main(int argc, char** argv)
240{
241 try {
242 return repo::main(argc, argv);
243 }
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800244 catch (const std::exception& e) {
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700245 std::cerr << "ERROR: " << e.what() << std::endl;
246 return 2;
247 }
248}