blob: be51b34d71e48d56da9abf5e07727dd6a573ac3c [file] [log] [blame]
Weiqi Shi9a223892014-08-24 18:42:58 -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#include "../src/common.hpp"
21#include "config.hpp"
22#include <string>
23#include <sqlite3.h>
24#include <boost/property_tree/ptree.hpp>
25#include <boost/property_tree/info_parser.hpp>
26
27namespace repo {
28
29using namespace ndn::time;
30
31void
32printUsage(const char* programName)
33{
34
35 std::cout
36 << "Usage:\n"
37 << " " << programName << " [-c <path/to/repo-ng.conf>] [-n] [-h]\n"
38 << "\n"
39 << "List names of Data packets in NDN repository. "
40 << "By default, all names will include the implicit digest of Data packets\n"
41 << "\n"
42 << "Options:\n"
43 << " -h: show help message\n"
44 << " -c: set config file path\n"
45 << " -n: do not show implicit digest\n"
46 << std::endl;
47 ;
48}
49
50class RepoEnumerator
51{
52public:
53 class Error : public std::runtime_error
54 {
55 public:
56 explicit
57 Error(const std::string& what)
58 : std::runtime_error(what)
59 {
60 }
61 };
62
63public:
64 RepoEnumerator(const std::string& configFile);
65
66 uint64_t
67 enumerate(bool showImplicitDigest);
68
69private:
70 void
71 readConfig(const std::string& configFile);
72
73private:
74 sqlite3* m_db;
75 std::string m_dbPath;
76};
77
78RepoEnumerator::RepoEnumerator(const std::string& configFile)
79{
80 readConfig(configFile);
81 char* errMsg = 0;
82 int rc = sqlite3_open_v2(m_dbPath.c_str(), &m_db,
83 SQLITE_OPEN_READONLY,
84 #ifdef DISABLE_SQLITE3_FS_LOCKING
85 "unix-dotfile"
86 #else
87 0
88 #endif
89 );
90 if (rc != SQLITE_OK) {
91 throw Error("Database file open failure");
92 }
93 sqlite3_exec(m_db, "PRAGMA synchronous = OFF", 0, 0, &errMsg);
94 sqlite3_exec(m_db, "PRAGMA journal_mode = WAL", 0, 0, &errMsg);
95}
96
97void
98RepoEnumerator::readConfig(const std::string& configFile)
99{
100 if (configFile.empty()) {
101 throw Error("Invalid configuration file name");
102 }
103
104 std::ifstream fin(configFile.c_str());
105 if (!fin.is_open())
106 throw Error("failed to open configuration file '" + configFile + "'");
107
108 using namespace boost::property_tree;
109 ptree propertyTree;
110 try {
111 read_info(fin, propertyTree);
112 }
113 catch (ptree_error& e) {
114 throw Error("failed to read configuration file '" + configFile + "'");
115 }
116 ptree repoConf = propertyTree.get_child("repo");
117 m_dbPath = repoConf.get<std::string>("storage.path");
118 m_dbPath += "/ndn_repo.db";
119}
120
121uint64_t
122RepoEnumerator::enumerate(bool showImplicitDigest)
123{
124 sqlite3_stmt* m_stmt = 0;
125 int rc = SQLITE_DONE;
126 string sql = string("SELECT id, name, keylocatorHash FROM NDN_REPO;");
127 rc = sqlite3_prepare_v2(m_db, sql.c_str(), -1, &m_stmt, 0);
128 if (rc != SQLITE_OK)
129 throw Error("Initiation Read Entries from Database Prepare error");
130 uint64_t entryNumber = 0;
131 while (true) {
132 rc = sqlite3_step(m_stmt);
133 if (rc == SQLITE_ROW) {
134 Name name;
135 name.wireDecode(Block(sqlite3_column_blob(m_stmt, 1),
136 sqlite3_column_bytes(m_stmt, 1)));
137 try {
138 if (showImplicitDigest) {
139 std::cout << name << std::endl;
140 }
141 else {
142 std::cout << name.getPrefix(-1) << std::endl;
143 }
144 }
145 catch (...){
146 sqlite3_finalize(m_stmt);
147 throw;
148 }
149 entryNumber++;
150 }
151 else if (rc == SQLITE_DONE) {
152 sqlite3_finalize(m_stmt);
153 break;
154 }
155 else {
156 sqlite3_finalize(m_stmt);
157 throw Error("Initiation Read Entries error");
158 }
159 }
160 return entryNumber;
161}
162
163int
164main(int argc, char** argv)
165{
166 string configPath = DEFAULT_CONFIG_FILE;
167 bool showImplicitDigest = true;
168 int opt;
169 while ((opt = getopt(argc, argv, "hc:n")) != -1) {
170 switch (opt) {
171 case 'h':
172 printUsage(argv[0]);
173 return 0;
174 case 'c':
175 configPath = string(optarg);
176 break;
177 case 'n':
178 showImplicitDigest = false;
179 break;
180 default:
181 break;
182 }
183 }
184
185 RepoEnumerator instance(configPath);
186 uint64_t count = instance.enumerate(showImplicitDigest);
187 std::cerr << "Total number of data = " << count << std::endl;
188 return 0;
189}
190
191} // namespace repo
192
193
194int
195main(int argc, char** argv)
196{
197 try {
198 return repo::main(argc, argv);
199 }
200 catch (std::exception& e) {
201 std::cerr << "ERROR: " << e.what() << std::endl;
202 return 2;
203 }
204}