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 <IceUtil/Options.h>
11 #include <IceUtil/FileUtil.h>
12 #include <Ice/Ice.h>
13 #include <Ice/ConsoleUtil.h>
14 #include <IceDB/IceDB.h>
15 #include <IceStorm/DBTypes.h>
16 #include <IceUtil/DisableWarnings.h>
17 #include <fstream>
18 
19 using namespace std;
20 using namespace Ice;
21 using namespace IceInternal;
22 using namespace IceStorm;
23 using namespace IceStormElection;
24 
25 class Client : public Ice::Application
26 {
27 public:
28 
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 <<
54  "Options:\n"
55  "-h, --help Show this message.\n"
56  "-v, --version Display version.\n"
57  "--import FILE Import database from FILE.\n"
58  "--export FILE Export database to FILE.\n"
59  "--dbhome DIR Source or target database environment.\n"
60  "--dbpath DIR Source or target database environment.\n"
61  "--mapsize VALUE Set LMDB map size in MB (optional, import only).\n"
62  "-d, --debug Print debug messages.\n"
63  ;
64 }
65 
66 int
67 Client::run(int argc, char* argv[])
68 {
69  IceUtilInternal::Options opts;
70  opts.addOpt("h", "help");
71  opts.addOpt("v", "version");
72  opts.addOpt("d", "debug");
73  opts.addOpt("", "import", IceUtilInternal::Options::NeedArg);
74  opts.addOpt("", "export", IceUtilInternal::Options::NeedArg);
75  opts.addOpt("", "dbhome", IceUtilInternal::Options::NeedArg);
76  opts.addOpt("", "dbpath", IceUtilInternal::Options::NeedArg);
77  opts.addOpt("", "mapsize", IceUtilInternal::Options::NeedArg);
78 
79  vector<string> args;
80  try
81  {
82  args = opts.parse(argc, const_cast<const char**>(argv));
83  }
84  catch (const IceUtilInternal::BadOptException& e)
85  {
86  consoleErr << argv[0] << ": " << e.reason << endl;
87  usage();
88  return EXIT_FAILURE;
89  }
90  if (!args.empty())
91  {
92  consoleErr << argv[0] << ": too many arguments" << endl;
93  usage();
94  return EXIT_FAILURE;
95  }
96 
97  if (opts.isSet("help"))
98  {
99  usage();
100  return EXIT_SUCCESS;
101  }
102 
103  if (opts.isSet("version"))
104  {
105  consoleOut << ICE_STRING_VERSION << endl;
106  return EXIT_SUCCESS;
107  }
108 
109  if (!(opts.isSet("import") ^ opts.isSet("export")))
110  {
111  consoleErr << argv[0] << ": either --import or --export must be set" << endl;
112  usage();
113  return EXIT_FAILURE;
114  }
115 
116  if (!(opts.isSet("dbhome") ^ opts.isSet("dbpath")))
117  {
118  consoleErr << argv[0] << ": set the database environment directory with either --dbhome or --dbpath" << 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 << endl;
151 
153  {
154  consoleErr << argv[0] << ": output directory does not exist: " << dbPath << endl;
155  return EXIT_FAILURE;
156  }
157 
158  if (!IceUtilInternal::isEmptyDirectory(dbPath))
159  {
160  consoleErr << argv[0] << ": output directory is not empty: " << dbPath << endl;
161  return EXIT_FAILURE;
162  }
163 
164  ifstream fs(IceUtilInternal::streamFilename(dbFile).c_str(), ios::binary);
165  if (fs.fail())
166  {
167  consoleErr << argv[0] << ": could not open input file: " << strerror(errno) << endl;
168  return EXIT_FAILURE;
169  }
170  fs.unsetf(ios::skipws);
171 
172  fs.seekg(0, ios::end);
173  streampos fileSize = fs.tellg();
174 
175  if (!fileSize)
176  {
177  fs.close();
178  consoleErr << argv[0] << ": empty input file" << endl;
179  return EXIT_FAILURE;
180  }
181 
182  fs.seekg(0, ios::beg);
183 
184  vector<Ice::Byte> buf;
185  buf.reserve(static_cast<size_t>(fileSize));
186  buf.insert(buf.begin(), istream_iterator<Ice::Byte>(fs), istream_iterator<Ice::Byte>());
187 
188  fs.close();
189 
190  string type;
191  int version;
192 
193  Ice::InputStream stream(communicator(), dbContext.encoding, buf);
194  stream.read(type);
195  if (type != "IceStorm")
196  {
197  consoleErr << argv[0] << ": incorrect input file type: " << type << endl;
198  return EXIT_FAILURE;
199  }
200  stream.read(version);
201  stream.read(data);
202 
203  {
204  IceDB::Env env(dbPath, 2, mapSize);
205  IceDB::ReadWriteTxn txn(env);
206 
207  if (debug)
208  {
209  consoleOut << "Writing LLU Map:" << endl;
210  }
211 
213  lluMap(txn, "llu", dbContext, MDB_CREATE);
214 
215  for (StringLogUpdateDict::const_iterator p = data.llus.begin(); p != data.llus.end(); ++p)
216  {
217  if (debug)
218  {
219  consoleOut << " KEY = " << p->first << endl;
220  }
221  lluMap.put(txn, p->first, p->second);
222  }
223 
224  if (debug)
225  {
226  consoleOut << "Writing Subscriber Map:" << endl;
227  }
228 
230  subscriberMap(txn, "subscribers", dbContext, MDB_CREATE);
231 
232  for (SubscriberRecordDict::const_iterator q = data.subscribers.begin(); q != data.subscribers.end(); ++q)
233  {
234  if (debug)
235  {
236  consoleOut << " KEY = TOPIC(" << communicator()->identityToString(q->first.topic)
237  << ") ID(" << communicator()->identityToString(q->first.id) << ")" << endl;
238  }
239  subscriberMap.put(txn, q->first, q->second);
240  }
241 
242  txn.commit();
243  env.close();
244  }
245  }
246  else
247  {
248  consoleOut << "Exporting database from directory " << dbPath << " to file " << dbFile << endl;
249 
250  {
251  IceDB::Env env(dbPath, 2);
252  IceDB::ReadOnlyTxn txn(env);
253 
254  if (debug)
255  {
256  consoleOut << "Reading LLU Map:" << endl;
257  }
258 
260  lluMap(txn, "llu", dbContext, 0);
261 
262  string s;
263  LogUpdate llu;
265  while (lluCursor.get(s, llu, MDB_NEXT))
266  {
267  if (debug)
268  {
269  consoleOut << " KEY = " << s << endl;
270  }
271  data.llus.insert(std::make_pair(s, llu));
272  }
273  lluCursor.close();
274 
275  if (debug)
276  {
277  consoleOut << "Reading Subscriber Map:" << endl;
278  }
279 
281  subscriberMap(txn, "subscribers", dbContext, 0);
282 
284  SubscriberRecord record;
286  subCursor(subscriberMap, txn);
287  while (subCursor.get(key, record, MDB_NEXT))
288  {
289  if (debug)
290  {
291  consoleOut << " KEY = TOPIC(" << communicator()->identityToString(key.topic)
292  << ") ID(" << communicator()->identityToString(key.id) << ")" << endl;
293  }
294  data.subscribers.insert(std::make_pair(key, record));
295  }
296  subCursor.close();
297 
298  txn.rollback();
299  env.close();
300  }
301 
302  Ice::OutputStream stream(communicator(), dbContext.encoding);
303  stream.write("IceStorm");
304  stream.write(ICE_INT_VERSION);
305  stream.write(data);
306 
307  ofstream fs(IceUtilInternal::streamFilename(dbFile).c_str(), ios::binary);
308  if (fs.fail())
309  {
310  consoleErr << argv[0] << ": could not open output file: " << strerror(errno) << endl;
311  return EXIT_FAILURE;
312  }
313  fs.write(reinterpret_cast<const char*>(stream.b.begin()), stream.b.size());
314  fs.close();
315  }
316  }
317  catch (const IceUtil::Exception& ex)
318  {
319  consoleErr << argv[0] << ": " << (import ? "import" : "export") << " failed:\n" << ex << endl;
320  return EXIT_FAILURE;
321  }
322 
323  return EXIT_SUCCESS;
324 }
IceStorm
Definition: DBTypes.ice:22
IceDB::ReadWriteTxn
Definition: IceDB.h:206
IceDB::IceContext::encoding
Ice::EncodingVersion encoding
Definition: IceDB.h:502
IceStorm::SubscriberRecordKey::topic
::Ice::Identity topic
Definition: SubscriberRecord.h:151
IceStorm::SubscriberRecordKey
The key for persistent subscribers, or topics.
Definition: SubscriberRecord.h:149
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:100
IceDB::ReadOnlyTxn
Definition: IceDB.h:194
IceDB::getMapSize
ICE_DB_API size_t getMapSize(int)
IceStorm::SubscriberRecord
Used to store persistent information for persistent subscribers.
Definition: SubscriberRecord.h:214
IceDB::ReadOnlyCursor
Definition: IceDB.h:481
IceDB::IceContext::communicator
Ice::CommunicatorPtr communicator
Definition: IceDB.h:501
main
int main(int argc, char *argv[])
Definition: IceStormDB.cpp:41
IceDB::Env
Definition: IceDB.h:150
IceStormElection
Definition: DBTypes.ice:17
armarx::armem::server::ltm ::util::fs::directoryExists
bool directoryExists(const std::filesystem::path &p)
Definition: filesystem.cpp:118
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
DBTypes.h
IceDB::IceContext
Definition: IceDB.h:499
IceInternal
Definition: InstrumentationI.h:16
IceDB::Dbi
Definition: IceDB.h:242
q
#define q
IceStorm::AllData
Definition: DBTypes.ice:26
Ice
Definition: DBTypes.cpp:64
std
Definition: Application.h:66
IceStorm::SubscriberRecordKey::id
::Ice::Identity id
Definition: SubscriberRecord.h:152
Client::usage
void usage()
Definition: Admin.cpp:58
Client
Definition: Admin.cpp:25
Client::run
virtual int run(int, char *[])
Definition: Admin.cpp:71
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33