blob: 806c011a9aae87d4bab767cbc18abff4fb587a85 [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/*
Alexander Afanasyev42290b22017-03-09 12:58:29 -08003 * Copyright (c) 2014-2017, 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
Weiqi Shi68f2cf62014-08-26 12:35:45 -070038#include <boost/lexical_cast.hpp>
Davide Pesavento49f3a5f2017-09-23 01:36:33 -040039#include <fstream>
Weiqi Shi68f2cf62014-08-26 12:35:45 -070040#include <iostream>
Davide Pesavento49f3a5f2017-09-23 01:36:33 -040041#include <random>
42#include <string>
Weiqi Shi68f2cf62014-08-26 12:35:45 -070043
44namespace repo {
45
Davide Pesavento49f3a5f2017-09-23 01:36:33 -040046using ndn::time::milliseconds;
Weiqi Shi68f2cf62014-08-26 12:35:45 -070047
48static const milliseconds DEFAULT_TIME_INTERVAL(2000);
49
Davide Pesavento49f3a5f2017-09-23 01:36:33 -040050enum Mode {
Weiqi Shi68f2cf62014-08-26 12:35:45 -070051 AUTO,
52 READFILE
53};
54
55class Publisher
56{
57public:
58 class Error : public std::runtime_error
59 {
60 public:
61 explicit
62 Error(const std::string& what)
63 : std::runtime_error(what)
64 {
65 }
66 };
67
68public:
69 Publisher()
70 : mode(AUTO)
71 , dataPrefix(Name("/example/data"))
72 , timeInterval(DEFAULT_TIME_INTERVAL)
73 , duration(0)
74 , m_scheduler(m_face.getIoService())
Davide Pesavento49f3a5f2017-09-23 01:36:33 -040075 , m_randomEngine(std::random_device{}())
76 , m_randomDist(200, 1000)
77 , m_range([this] { return m_randomDist(m_randomEngine); })
Weiqi Shi68f2cf62014-08-26 12:35:45 -070078 {
79 }
80
81 void
82 run();
83
84 void
85 autoGenerate();
86
87 void
88 generateFromFile();
89
Alexander Afanasyev42290b22017-03-09 12:58:29 -080090 std::shared_ptr<ndn::Data>
Weiqi Shi68f2cf62014-08-26 12:35:45 -070091 createData(const ndn::Name& name);
Davide Pesavento49f3a5f2017-09-23 01:36:33 -040092
Weiqi Shi68f2cf62014-08-26 12:35:45 -070093public:
94 std::ifstream insertStream;
95 Mode mode;
96 Name dataPrefix;
97 milliseconds timeInterval;
98 milliseconds duration;
99
100private:
101 ndn::Face m_face;
102 ndn::Scheduler m_scheduler;
Davide Pesavento49f3a5f2017-09-23 01:36:33 -0400103 std::mt19937 m_randomEngine;
104 std::uniform_int_distribution<unsigned int> m_randomDist;
105 std::function<unsigned int(void)> m_range;
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700106};
107
108void
109Publisher::run()
110{
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700111 if (mode == AUTO) {
112 m_scheduler.scheduleEvent(timeInterval,
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800113 bind(&Publisher::autoGenerate, this));
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700114 }
115 else {
116 m_scheduler.scheduleEvent(timeInterval,
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800117 bind(&Publisher::generateFromFile, this));
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700118 }
119 m_face.processEvents(duration);
120}
121
122void
123Publisher::autoGenerate()
124{
125 Name name = dataPrefix;
126 name.appendNumber(m_range());
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800127 std::shared_ptr<Data> data = createData(name);
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700128 // std::cout<<"data name = "<<data->getName()<<std::endl;
129 m_face.put(*data);
130 m_scheduler.scheduleEvent(timeInterval,
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800131 bind(&Publisher::autoGenerate, this));
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700132}
133
134void
135Publisher::generateFromFile()
136{
137 if (insertStream.eof()) {
138 m_face.getIoService().stop();
139 return;
140 }
141 std::string name;
142 getline(insertStream, name);
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800143 std::shared_ptr<Data> data = createData(Name(name));
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700144 m_face.put(*data);
145 m_scheduler.scheduleEvent(timeInterval,
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800146 bind(&Publisher::generateFromFile, this));
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700147}
148
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800149std::shared_ptr<Data>
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700150Publisher::createData(const Name& name)
151{
152 static ndn::KeyChain keyChain;
153 static std::vector<uint8_t> content(1500, '-');
154
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800155 std::shared_ptr<ndn::Data> data = std::make_shared<Data>();
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700156 data->setName(name);
157 data->setContent(&content[0], content.size());
158 keyChain.sign(*data);
159 return data;
160}
161
162static void
163usage()
164{
165 std::cerr
166 << " Publisher [-d dataPrefix] [-f filename] [-s duration time] [-t generate time interval] \n"
167 << " -d: specify the data prefix publisher generate\n"
168 << " -f: specify filename that publish would read from\n"
169 << " -s: specify the time duration of generate data\n"
170 << " -t: specify the time interval between two data generated\n"
171 << std::endl;
172 exit(1);
173}
174
Davide Pesavento49f3a5f2017-09-23 01:36:33 -0400175static int
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700176main(int argc, char** argv)
177{
178 Publisher generator;
179 bool isAuto = false;
180 bool isRead = false;
181 int opt;
182 while ((opt = getopt(argc, argv, "d:f:s:t:")) != -1) {
183 switch (opt) {
184 case 'd':
185 {
186 generator.dataPrefix = Name(std::string(optarg));
187 generator.mode = AUTO;
188 isAuto = true;
189 }
190 break;
191 case 'f':
192 {
193 isRead = true;
194 generator.mode = READFILE;
195 std::string str = std::string(optarg);
196 generator.insertStream.open(str.c_str());
197 if (!generator.insertStream.is_open()) {
198 std::cerr << "ERROR: cannot open " << std::string(optarg) << std::endl;
199 return 1;
200 }
201 }
202 break;
203 case 's':
204 try {
205 generator.duration = milliseconds(boost::lexical_cast<uint64_t>(optarg));
206 }
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800207 catch (const boost::bad_lexical_cast&) {
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700208 std::cerr << "-s option should be an integer.";
209 return 1;
210 }
211 break;
212 case 't':
213 try {
214 generator.timeInterval = milliseconds(boost::lexical_cast<uint64_t>(optarg));
215 }
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800216 catch (const boost::bad_lexical_cast&) {
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700217 std::cerr << "-t option should be an integer.";
218 return 1;
219 }
220 break;
221 default:
222 usage();
223 break;
224 }
225 }
226
227 argc -= optind;
228 argv += optind;
229
230 if (argc != 0)
231 usage();
232
233 if (isAuto && isRead)
234 usage();
235
236 generator.run();
237 return 0;
238}
239
240} // namespace repo
241
242int
243main(int argc, char** argv)
244{
245 try {
246 return repo::main(argc, argv);
247 }
Alexander Afanasyev42290b22017-03-09 12:58:29 -0800248 catch (const std::exception& e) {
Weiqi Shi68f2cf62014-08-26 12:35:45 -0700249 std::cerr << "ERROR: " << e.what() << std::endl;
250 return 2;
251 }
252}