blob: 73f731a1d13bc8def35f59bc28f3ac9d2f5d6598 [file] [log] [blame]
Weiqi Shi68f2cf62014-08-26 12:35:45 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2014, Regents of the University of California.
4 *
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/>.
18 */
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
24 * <http://redmine.named-data.net/projects/repo-ng/wiki/Watched_Prefix_Insertion_Protocol>
25 * <http://redmine.named-data.net/projects/repo-ng/wiki/Basic_Repo_Insertion_Protocol>
26 *
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"
37#include <fstream>
38#include <boost/filesystem.hpp>
39#include <boost/lexical_cast.hpp>
40#include <string>
41#include <boost/random.hpp>
42#include <iostream>
43
44namespace repo {
45
46using namespace ndn::time;
47
48static const milliseconds DEFAULT_TIME_INTERVAL(2000);
49
50enum Mode
51{
52 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())
76 , m_randomGenerator(static_cast<unsigned int> (0))
77 , m_range(m_randomGenerator, boost::uniform_int<> (200,1000))
78 {
79 }
80
81 void
82 run();
83
84 void
85 autoGenerate();
86
87 void
88 generateFromFile();
89
90 ndn::shared_ptr<ndn::Data>
91 createData(const ndn::Name& name);
92public:
93 std::ifstream insertStream;
94 Mode mode;
95 Name dataPrefix;
96 milliseconds timeInterval;
97 milliseconds duration;
98
99private:
100 ndn::Face m_face;
101 ndn::Scheduler m_scheduler;
102 boost::mt19937 m_randomGenerator;
103 boost::variate_generator<boost::mt19937&, boost::uniform_int<> > m_range;
104};
105
106void
107Publisher::run()
108{
109
110 if (mode == AUTO) {
111 m_scheduler.scheduleEvent(timeInterval,
112 ndn::bind(&Publisher::autoGenerate, this));
113 }
114 else {
115 m_scheduler.scheduleEvent(timeInterval,
116 ndn::bind(&Publisher::generateFromFile, this));
117 }
118 m_face.processEvents(duration);
119}
120
121void
122Publisher::autoGenerate()
123{
124 Name name = dataPrefix;
125 name.appendNumber(m_range());
126 ndn::shared_ptr<Data> data = createData(name);
127 // std::cout<<"data name = "<<data->getName()<<std::endl;
128 m_face.put(*data);
129 m_scheduler.scheduleEvent(timeInterval,
130 ndn::bind(&Publisher::autoGenerate, this));
131}
132
133void
134Publisher::generateFromFile()
135{
136 if (insertStream.eof()) {
137 m_face.getIoService().stop();
138 return;
139 }
140 std::string name;
141 getline(insertStream, name);
142 ndn::shared_ptr<Data> data = createData(Name(name));
143 m_face.put(*data);
144 m_scheduler.scheduleEvent(timeInterval,
145 ndn::bind(&Publisher::generateFromFile, this));
146}
147
148ndn::shared_ptr<Data>
149Publisher::createData(const Name& name)
150{
151 static ndn::KeyChain keyChain;
152 static std::vector<uint8_t> content(1500, '-');
153
154 ndn::shared_ptr<ndn::Data> data = ndn::make_shared<Data>();
155 data->setName(name);
156 data->setContent(&content[0], content.size());
157 keyChain.sign(*data);
158 return data;
159}
160
161static void
162usage()
163{
164 std::cerr
165 << " Publisher [-d dataPrefix] [-f filename] [-s duration time] [-t generate time interval] \n"
166 << " -d: specify the data prefix publisher generate\n"
167 << " -f: specify filename that publish would read from\n"
168 << " -s: specify the time duration of generate data\n"
169 << " -t: specify the time interval between two data generated\n"
170 << std::endl;
171 exit(1);
172}
173
174int
175main(int argc, char** argv)
176{
177 Publisher generator;
178 bool isAuto = false;
179 bool isRead = false;
180 int opt;
181 while ((opt = getopt(argc, argv, "d:f:s:t:")) != -1) {
182 switch (opt) {
183 case 'd':
184 {
185 generator.dataPrefix = Name(std::string(optarg));
186 generator.mode = AUTO;
187 isAuto = true;
188 }
189 break;
190 case 'f':
191 {
192 isRead = true;
193 generator.mode = READFILE;
194 std::string str = std::string(optarg);
195 generator.insertStream.open(str.c_str());
196 if (!generator.insertStream.is_open()) {
197 std::cerr << "ERROR: cannot open " << std::string(optarg) << std::endl;
198 return 1;
199 }
200 }
201 break;
202 case 's':
203 try {
204 generator.duration = milliseconds(boost::lexical_cast<uint64_t>(optarg));
205 }
206 catch (boost::bad_lexical_cast&) {
207 std::cerr << "-s option should be an integer.";
208 return 1;
209 }
210 break;
211 case 't':
212 try {
213 generator.timeInterval = milliseconds(boost::lexical_cast<uint64_t>(optarg));
214 }
215 catch (boost::bad_lexical_cast&) {
216 std::cerr << "-t option should be an integer.";
217 return 1;
218 }
219 break;
220 default:
221 usage();
222 break;
223 }
224 }
225
226 argc -= optind;
227 argv += optind;
228
229 if (argc != 0)
230 usage();
231
232 if (isAuto && isRead)
233 usage();
234
235 generator.run();
236 return 0;
237}
238
239} // namespace repo
240
241int
242main(int argc, char** argv)
243{
244 try {
245 return repo::main(argc, argv);
246 }
247 catch (std::exception& e) {
248 std::cerr << "ERROR: " << e.what() << std::endl;
249 return 2;
250 }
251}