blob: 92dedd334b61d7de8e8a58cb1e65f7c6cb547f9b [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) {
113 m_scheduler.scheduleEvent(timeInterval,
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800114 bind(&Publisher::autoGenerate, this));
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700115 }
116 else {
117 m_scheduler.scheduleEvent(timeInterval,
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800118 bind(&Publisher::generateFromFile, this));
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700119 }
120 m_face.processEvents(duration);
121}
122
123void
124Publisher::autoGenerate()
125{
126 Name name = dataPrefix;
127 name.appendNumber(m_range());
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800128 std::shared_ptr<Data> data = createData(name);
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700129 // std::cout<<"data name = "<<data->getName()<<std::endl;
130 m_face.put(*data);
131 m_scheduler.scheduleEvent(timeInterval,
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800132 bind(&Publisher::autoGenerate, this));
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700133}
134
135void
136Publisher::generateFromFile()
137{
138 if (insertStream.eof()) {
139 m_face.getIoService().stop();
140 return;
141 }
142 std::string name;
143 getline(insertStream, name);
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800144 std::shared_ptr<Data> data = createData(Name(name));
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700145 m_face.put(*data);
146 m_scheduler.scheduleEvent(timeInterval,
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800147 bind(&Publisher::generateFromFile, this));
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700148}
149
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800150std::shared_ptr<Data>
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700151Publisher::createData(const Name& name)
152{
153 static ndn::KeyChain keyChain;
154 static std::vector<uint8_t> content(1500, '-');
155
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800156 std::shared_ptr<ndn::Data> data = std::make_shared<Data>();
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700157 data->setName(name);
158 data->setContent(&content[0], content.size());
159 keyChain.sign(*data);
160 return data;
161}
162
163static void
164usage()
165{
166 std::cerr
167 << " Publisher [-d dataPrefix] [-f filename] [-s duration time] [-t generate time interval] \n"
168 << " -d: specify the data prefix publisher generate\n"
169 << " -f: specify filename that publish would read from\n"
170 << " -s: specify the time duration of generate data\n"
171 << " -t: specify the time interval between two data generated\n"
172 << std::endl;
173 exit(1);
174}
175
Davide Pesavento49f3a5f2017-09-23 01:36:33 -0400176static int
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700177main(int argc, char** argv)
178{
179 Publisher generator;
180 bool isAuto = false;
181 bool isRead = false;
182 int opt;
183 while ((opt = getopt(argc, argv, "d:f:s:t:")) != -1) {
184 switch (opt) {
185 case 'd':
186 {
187 generator.dataPrefix = Name(std::string(optarg));
188 generator.mode = AUTO;
189 isAuto = true;
190 }
191 break;
192 case 'f':
193 {
194 isRead = true;
195 generator.mode = READFILE;
196 std::string str = std::string(optarg);
197 generator.insertStream.open(str.c_str());
198 if (!generator.insertStream.is_open()) {
199 std::cerr << "ERROR: cannot open " << std::string(optarg) << std::endl;
200 return 1;
201 }
202 }
203 break;
204 case 's':
205 try {
206 generator.duration = milliseconds(boost::lexical_cast<uint64_t>(optarg));
207 }
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800208 catch (const boost::bad_lexical_cast&) {
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700209 std::cerr << "-s option should be an integer.";
210 return 1;
211 }
212 break;
213 case 't':
214 try {
215 generator.timeInterval = milliseconds(boost::lexical_cast<uint64_t>(optarg));
216 }
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800217 catch (const boost::bad_lexical_cast&) {
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700218 std::cerr << "-t option should be an integer.";
219 return 1;
220 }
221 break;
222 default:
223 usage();
224 break;
225 }
226 }
227
228 argc -= optind;
229 argv += optind;
230
231 if (argc != 0)
232 usage();
233
234 if (isAuto && isRead)
235 usage();
236
237 generator.run();
238 return 0;
239}
240
241} // namespace repo
242
243int
244main(int argc, char** argv)
245{
246 try {
247 return repo::main(argc, argv);
248 }
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800249 catch (const std::exception& e) {
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700250 std::cerr << "ERROR: " << e.what() << std::endl;
251 return 2;
252 }
253}