IceStormDB.cpp
Go to the documentation of this file.
1 // **********************************************************************
2 //
3 // Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved.
4 //
5 // This copy of Ice is licensed to you under the terms described in the
6 // ICE_LICENSE file included in this distribution.
7 //
8 // **********************************************************************
9 
10 #include <fstream>
11 
12 #include <Ice/ConsoleUtil.h>
13 #include <Ice/Ice.h>
14 #include <IceDB/IceDB.h>
15 #include <IceStorm/DBTypes.h>
16 #include <IceUtil/DisableWarnings.h>
17 #include <IceUtil/FileUtil.h>
18 #include <IceUtil/Options.h>
19 
20 using namespace std;
21 using namespace Ice;
22 using namespace IceInternal;
23 using namespace IceStorm;
24 using namespace IceStormElection;
25 
26 class Client : public Ice::Application
27 {
28 public:
29  void usage();
30  virtual int run(int, char*[]);
31 };
32 
33 #ifdef _WIN32
34 
35 int
36 wmain(int argc, wchar_t* argv[])
37 
38 #else
39 
40 int
41 main(int argc, char* argv[])
42 
43 #endif
44 {
45  Client app;
46  return app.main(argc, argv);
47 }
48 
49 void
51 {
52  consoleErr << "Usage: " << appName() << " <options>\n";
53  consoleErr << "Options:\n"
54  "-h, --help Show this message.\n"
55  "-v, --version Display version.\n"
56  "--import FILE Import database from FILE.\n"
57  "--export FILE Export database to FILE.\n"
58  "--dbhome DIR Source or target database environment.\n"
59  "--dbpath DIR Source or target database environment.\n"
60  "--mapsize VALUE Set LMDB map size in MB (optional, import only).\n"
61  "-d, --debug Print debug messages.\n";
62 }
63 
64 int
65 Client::run(int argc, char* argv[])
66 {
67  IceUtilInternal::Options opts;
68  opts.addOpt("h", "help");
69  opts.addOpt("v", "version");
70  opts.addOpt("d", "debug");
71  opts.addOpt("", "import", IceUtilInternal::Options::NeedArg);
72  opts.addOpt("", "export", IceUtilInternal::Options::NeedArg);
73  opts.addOpt("", "dbhome", IceUtilInternal::Options::NeedArg);
74  opts.addOpt("", "dbpath", IceUtilInternal::Options::NeedArg);
75  opts.addOpt("", "mapsize", IceUtilInternal::Options::NeedArg);
76 
77  vector<string> args;
78  try
79  {
80  args = opts.parse(argc, const_cast<const char**>(argv));
81  }
82  catch (const IceUtilInternal::BadOptException& e)
83  {
84  consoleErr << argv[0] << ": " << e.reason << endl;
85  usage();
86  return EXIT_FAILURE;
87  }
88  if (!args.empty())
89  {
90  consoleErr << argv[0] << ": too many arguments" << endl;
91  usage();
92  return EXIT_FAILURE;
93  }
94 
95  if (opts.isSet("help"))
96  {
97  usage();
98  return EXIT_SUCCESS;
99  }
100 
101  if (opts.isSet("version"))
102  {
103  consoleOut << ICE_STRING_VERSION << endl;
104  return EXIT_SUCCESS;
105  }
106 
107  if (!(opts.isSet("import") ^ opts.isSet("export")))
108  {
109  consoleErr << argv[0] << ": either --import or --export must be set" << endl;
110  usage();
111  return EXIT_FAILURE;
112  }
113 
114  if (!(opts.isSet("dbhome") ^ opts.isSet("dbpath")))
115  {
116  consoleErr << argv[0]
117  << ": set the database environment directory with either --dbhome or --dbpath"
118  << endl;
119  usage();
120  return EXIT_FAILURE;
121  }
122 
123  bool debug = opts.isSet("debug");
124  bool import = opts.isSet("import");
125  string dbFile = opts.optArg(import ? "import" : "export");
126  string dbPath;
127  if (opts.isSet("dbhome"))
128  {
129  dbPath = opts.optArg("dbhome");
130  }
131  else
132  {
133  dbPath = opts.optArg("dbpath");
134  }
135 
136  string mapSizeStr = opts.optArg("mapsize");
137  size_t mapSize = IceDB::getMapSize(atoi(mapSizeStr.c_str()));
138 
139  try
140  {
142 
144  dbContext.communicator = communicator();
145  dbContext.encoding.major = 1;
146  dbContext.encoding.minor = 1;
147 
148  if (import)
149  {
150  consoleOut << "Importing database to directory " << dbPath << " from file " << dbFile
151  << endl;
152 
154  {
155  consoleErr << argv[0] << ": output directory does not exist: " << dbPath << endl;
156  return EXIT_FAILURE;
157  }
158 
159  if (!IceUtilInternal::isEmptyDirectory(dbPath))
160  {
161  consoleErr << argv[0] << ": output directory is not empty: " << dbPath << endl;
162  return EXIT_FAILURE;
163  }
164 
165  ifstream fs(IceUtilInternal::streamFilename(dbFile).c_str(), ios::binary);
166  if (fs.fail())
167  {
168  consoleErr << argv[0] << ": could not open input file: " << strerror(errno) << endl;
169  return EXIT_FAILURE;
170  }
171  fs.unsetf(ios::skipws);
172 
173  fs.seekg(0, ios::end);
174  streampos fileSize = fs.tellg();
175 
176  if (!fileSize)
177  {
178  fs.close();
179  consoleErr << argv[0] << ": empty input file" << endl;
180  return EXIT_FAILURE;
181  }
182 
183  fs.seekg(0, ios::beg);
184 
185  vector<Ice::Byte> buf;
186  buf.reserve(static_cast<size_t>(fileSize));
187  buf.insert(buf.begin(), istream_iterator<Ice::Byte>(fs), istream_iterator<Ice::Byte>());
188 
189  fs.close();
190 
191  string type;
192  int version;
193 
194  Ice::InputStream stream(communicator(), dbContext.encoding, buf);
195  stream.read(type);
196  if (type != "IceStorm")
197  {
198  consoleErr << argv[0] << ": incorrect input file type: " << type << endl;
199  return EXIT_FAILURE;
200  }
201  stream.read(version);
202  stream.read(data);
203 
204  {
205  IceDB::Env env(dbPath, 2, mapSize);
206  IceDB::ReadWriteTxn txn(env);
207 
208  if (debug)
209  {
210  consoleOut << "Writing LLU Map:" << endl;
211  }
212 
214  txn, "llu", dbContext, MDB_CREATE);
215 
216  for (StringLogUpdateDict::const_iterator p = data.llus.begin();
217  p != data.llus.end();
218  ++p)
219  {
220  if (debug)
221  {
222  consoleOut << " KEY = " << p->first << endl;
223  }
224  lluMap.put(txn, p->first, p->second);
225  }
226 
227  if (debug)
228  {
229  consoleOut << "Writing Subscriber Map:" << endl;
230  }
231 
232  IceDB::
233  Dbi<SubscriberRecordKey, SubscriberRecord, IceDB::IceContext, Ice::OutputStream>
234  subscriberMap(txn, "subscribers", dbContext, MDB_CREATE);
235 
236  for (SubscriberRecordDict::const_iterator q = data.subscribers.begin();
237  q != data.subscribers.end();
238  ++q)
239  {
240  if (debug)
241  {
242  consoleOut << " KEY = TOPIC("
243  << communicator()->identityToString(q->first.topic) << ") ID("
244  << communicator()->identityToString(q->first.id) << ")" << endl;
245  }
246  subscriberMap.put(txn, q->first, q->second);
247  }
248 
249  txn.commit();
250  env.close();
251  }
252  }
253  else
254  {
255  consoleOut << "Exporting database from directory " << dbPath << " to file " << dbFile
256  << endl;
257 
258  {
259  IceDB::Env env(dbPath, 2);
260  IceDB::ReadOnlyTxn txn(env);
261 
262  if (debug)
263  {
264  consoleOut << "Reading LLU Map:" << endl;
265  }
266 
268  txn, "llu", dbContext, 0);
269 
270  string s;
271  LogUpdate llu;
273  lluCursor(lluMap, txn);
274  while (lluCursor.get(s, llu, MDB_NEXT))
275  {
276  if (debug)
277  {
278  consoleOut << " KEY = " << s << endl;
279  }
280  data.llus.insert(std::make_pair(s, llu));
281  }
282  lluCursor.close();
283 
284  if (debug)
285  {
286  consoleOut << "Reading Subscriber Map:" << endl;
287  }
288 
289  IceDB::
290  Dbi<SubscriberRecordKey, SubscriberRecord, IceDB::IceContext, Ice::OutputStream>
291  subscriberMap(txn, "subscribers", dbContext, 0);
292 
294  SubscriberRecord record;
298  Ice::OutputStream>
299  subCursor(subscriberMap, txn);
300  while (subCursor.get(key, record, MDB_NEXT))
301  {
302  if (debug)
303  {
304  consoleOut << " KEY = TOPIC("
305  << communicator()->identityToString(key.topic) << ") ID("
306  << communicator()->identityToString(key.id) << ")" << endl;
307  }
308  data.subscribers.insert(std::make_pair(key, record));
309  }
310  subCursor.close();
311 
312  txn.rollback();
313  env.close();
314  }
315 
316  Ice::OutputStream stream(communicator(), dbContext.encoding);
317  stream.write("IceStorm");
318  stream.write(ICE_INT_VERSION);
319  stream.write(data);
320 
321  ofstream fs(IceUtilInternal::streamFilename(dbFile).c_str(), ios::binary);
322  if (fs.fail())
323  {
324  consoleErr << argv[0] << ": could not open output file: " << strerror(errno)
325  << endl;
326  return EXIT_FAILURE;
327  }
328  fs.write(reinterpret_cast<const char*>(stream.b.begin()), stream.b.size());
329  fs.close();
330  }
331  }
332  catch (const IceUtil::Exception& ex)
333  {
334  consoleErr << argv[0] << ": " << (import ? "import" : "export") << " failed:\n"
335  << ex << endl;
336  return EXIT_FAILURE;
337  }
338 
339  return EXIT_SUCCESS;
340 }
IceStorm
Definition: DBTypes.ice:22
IceDB::ReadWriteTxn
Definition: IceDB.h:194
IceDB::IceContext::encoding
Ice::EncodingVersion encoding
Definition: IceDB.h:490
IceStorm::SubscriberRecordKey::topic
::Ice::Identity topic
Definition: SubscriberRecord.h:161
IceStorm::SubscriberRecordKey
The key for persistent subscribers, or topics.
Definition: SubscriberRecord.h:159
IceDB.h
IceStormInternal::dbContext
IceDB::IceContext dbContext
Definition: Util.cpp:19
IceStormElection::LogUpdate
A struct used for marking the last log update.
Definition: LLURecord.h:102
IceDB::ReadOnlyTxn
Definition: IceDB.h:183
IceDB::getMapSize
ICE_DB_API size_t getMapSize(int)
IceStorm::SubscriberRecord
Used to store persistent information for persistent subscribers.
Definition: SubscriberRecord.h:233
IceDB::ReadOnlyCursor
Definition: IceDB.h:469
IceDB::IceContext::communicator
Ice::CommunicatorPtr communicator
Definition: IceDB.h:489
main
int main(int argc, char *argv[])
Definition: IceStormDB.cpp:41
IceDB::Env
Definition: IceDB.h:144
IceStormElection
Definition: DBTypes.ice:17
armarx::armem::server::ltm ::util::fs::directoryExists
bool directoryExists(const std::filesystem::path &p)
Definition: filesystem.cpp:133
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
DBTypes.h
IceDB::IceContext
Definition: IceDB.h:487
IceInternal
This file is part of ArmarX.
Definition: InstrumentationI.h:16
IceDB::Dbi
Definition: IceDB.h:226
q
#define q
IceStorm::AllData
Definition: DBTypes.ice:26
Ice
Definition: DBTypes.cpp:63
std
Definition: Application.h:66
IceStorm::SubscriberRecordKey::id
::Ice::Identity id
Definition: SubscriberRecord.h:162
Client::usage
void usage()
Definition: Admin.cpp:58
Client
Definition: Admin.cpp:26
Client::run
virtual int run(int, char *[])
Definition: Admin.cpp:69
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33