| /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
| /** |
| * Copyright (c) 2014-2017, Regents of the University of California. |
| * |
| * This file is part of NDN repo-ng (Next generation of NDN repository). |
| * See AUTHORS.md for complete list of repo-ng authors and contributors. |
| * |
| * repo-ng is free software: you can redistribute it and/or modify it under the terms |
| * of the GNU General Public License as published by the Free Software Foundation, |
| * either version 3 of the License, or (at your option) any later version. |
| * |
| * repo-ng is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
| * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
| * PURPOSE. See the GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License along with |
| * repo-ng, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| /** |
| * This file demonstrates how to generate data to be stored in repo with repo watch |
| * protocol and repo insert protocol. |
| * The details of the protocols can be find here |
| * <https://redmine.named-data.net/projects/repo-ng/wiki/Watched_Prefix_Insertion_Protocol> |
| * <https://redmine.named-data.net/projects/repo-ng/wiki/Basic_Repo_Insertion_Protocol> |
| * |
| * This file is used for debugging purpose. There are two modes for users to assign |
| * names for the data. |
| * 1)read the data name from a specific file |
| * 2)input a prefix and a random version number will be added automatically |
| * Users need to run nfd and repo-ng and set up specific repo protocols mentioned |
| * above before running this program. |
| * The description of command parameter can be found in the function usage(). |
| */ |
| |
| #include "../src/common.hpp" |
| #include <fstream> |
| #include <boost/filesystem.hpp> |
| #include <boost/lexical_cast.hpp> |
| #include <string> |
| #include <boost/random.hpp> |
| #include <iostream> |
| |
| namespace repo { |
| |
| using namespace ndn::time; |
| |
| static const milliseconds DEFAULT_TIME_INTERVAL(2000); |
| |
| enum Mode |
| { |
| AUTO, |
| READFILE |
| }; |
| |
| class Publisher |
| { |
| public: |
| class Error : public std::runtime_error |
| { |
| public: |
| explicit |
| Error(const std::string& what) |
| : std::runtime_error(what) |
| { |
| } |
| }; |
| |
| public: |
| Publisher() |
| : mode(AUTO) |
| , dataPrefix(Name("/example/data")) |
| , timeInterval(DEFAULT_TIME_INTERVAL) |
| , duration(0) |
| , m_scheduler(m_face.getIoService()) |
| , m_randomGenerator(static_cast<unsigned int> (0)) |
| , m_range(m_randomGenerator, boost::uniform_int<> (200,1000)) |
| { |
| } |
| |
| void |
| run(); |
| |
| void |
| autoGenerate(); |
| |
| void |
| generateFromFile(); |
| |
| std::shared_ptr<ndn::Data> |
| createData(const ndn::Name& name); |
| public: |
| std::ifstream insertStream; |
| Mode mode; |
| Name dataPrefix; |
| milliseconds timeInterval; |
| milliseconds duration; |
| |
| private: |
| ndn::Face m_face; |
| ndn::Scheduler m_scheduler; |
| boost::mt19937 m_randomGenerator; |
| boost::variate_generator<boost::mt19937&, boost::uniform_int<> > m_range; |
| }; |
| |
| void |
| Publisher::run() |
| { |
| |
| if (mode == AUTO) { |
| m_scheduler.scheduleEvent(timeInterval, |
| bind(&Publisher::autoGenerate, this)); |
| } |
| else { |
| m_scheduler.scheduleEvent(timeInterval, |
| bind(&Publisher::generateFromFile, this)); |
| } |
| m_face.processEvents(duration); |
| } |
| |
| void |
| Publisher::autoGenerate() |
| { |
| Name name = dataPrefix; |
| name.appendNumber(m_range()); |
| std::shared_ptr<Data> data = createData(name); |
| // std::cout<<"data name = "<<data->getName()<<std::endl; |
| m_face.put(*data); |
| m_scheduler.scheduleEvent(timeInterval, |
| bind(&Publisher::autoGenerate, this)); |
| } |
| |
| void |
| Publisher::generateFromFile() |
| { |
| if (insertStream.eof()) { |
| m_face.getIoService().stop(); |
| return; |
| } |
| std::string name; |
| getline(insertStream, name); |
| std::shared_ptr<Data> data = createData(Name(name)); |
| m_face.put(*data); |
| m_scheduler.scheduleEvent(timeInterval, |
| bind(&Publisher::generateFromFile, this)); |
| } |
| |
| std::shared_ptr<Data> |
| Publisher::createData(const Name& name) |
| { |
| static ndn::KeyChain keyChain; |
| static std::vector<uint8_t> content(1500, '-'); |
| |
| std::shared_ptr<ndn::Data> data = std::make_shared<Data>(); |
| data->setName(name); |
| data->setContent(&content[0], content.size()); |
| keyChain.sign(*data); |
| return data; |
| } |
| |
| static void |
| usage() |
| { |
| std::cerr |
| << " Publisher [-d dataPrefix] [-f filename] [-s duration time] [-t generate time interval] \n" |
| << " -d: specify the data prefix publisher generate\n" |
| << " -f: specify filename that publish would read from\n" |
| << " -s: specify the time duration of generate data\n" |
| << " -t: specify the time interval between two data generated\n" |
| << std::endl; |
| exit(1); |
| } |
| |
| int |
| main(int argc, char** argv) |
| { |
| Publisher generator; |
| bool isAuto = false; |
| bool isRead = false; |
| int opt; |
| while ((opt = getopt(argc, argv, "d:f:s:t:")) != -1) { |
| switch (opt) { |
| case 'd': |
| { |
| generator.dataPrefix = Name(std::string(optarg)); |
| generator.mode = AUTO; |
| isAuto = true; |
| } |
| break; |
| case 'f': |
| { |
| isRead = true; |
| generator.mode = READFILE; |
| std::string str = std::string(optarg); |
| generator.insertStream.open(str.c_str()); |
| if (!generator.insertStream.is_open()) { |
| std::cerr << "ERROR: cannot open " << std::string(optarg) << std::endl; |
| return 1; |
| } |
| } |
| break; |
| case 's': |
| try { |
| generator.duration = milliseconds(boost::lexical_cast<uint64_t>(optarg)); |
| } |
| catch (const boost::bad_lexical_cast&) { |
| std::cerr << "-s option should be an integer."; |
| return 1; |
| } |
| break; |
| case 't': |
| try { |
| generator.timeInterval = milliseconds(boost::lexical_cast<uint64_t>(optarg)); |
| } |
| catch (const boost::bad_lexical_cast&) { |
| std::cerr << "-t option should be an integer."; |
| return 1; |
| } |
| break; |
| default: |
| usage(); |
| break; |
| } |
| } |
| |
| argc -= optind; |
| argv += optind; |
| |
| if (argc != 0) |
| usage(); |
| |
| if (isAuto && isRead) |
| usage(); |
| |
| generator.run(); |
| return 0; |
| } |
| |
| } // namespace repo |
| |
| int |
| main(int argc, char** argv) |
| { |
| try { |
| return repo::main(argc, argv); |
| } |
| catch (const std::exception& e) { |
| std::cerr << "ERROR: " << e.what() << std::endl; |
| return 2; |
| } |
| } |