summaryrefslogtreecommitdiff
path: root/cpp/src/Transform/TransformDB.cpp
diff options
context:
space:
mode:
authorMark Spruiell <mes@zeroc.com>2003-10-21 22:25:48 +0000
committerMark Spruiell <mes@zeroc.com>2003-10-21 22:25:48 +0000
commit623184c101c904eb0d456d325d3ced4d4475d3ae (patch)
tree56a4d02eeb1f966ad1f17405a9c6b2fe84e804e0 /cpp/src/Transform/TransformDB.cpp
parentFreeze Index Windows port (diff)
downloadice-623184c101c904eb0d456d325d3ced4d4475d3ae.tar.bz2
ice-623184c101c904eb0d456d325d3ced4d4475d3ae.tar.xz
ice-623184c101c904eb0d456d325d3ced4d4475d3ae.zip
initial check-in
Diffstat (limited to 'cpp/src/Transform/TransformDB.cpp')
-rw-r--r--cpp/src/Transform/TransformDB.cpp563
1 files changed, 563 insertions, 0 deletions
diff --git a/cpp/src/Transform/TransformDB.cpp b/cpp/src/Transform/TransformDB.cpp
new file mode 100644
index 00000000000..5fd6e75fa77
--- /dev/null
+++ b/cpp/src/Transform/TransformDB.cpp
@@ -0,0 +1,563 @@
+// **********************************************************************
+//
+// Copyright (c) 2003
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <Slice/Preprocessor.h>
+#include <Transform/Transformer.h>
+#include <Transform/TransformUtil.h>
+#include <db_cxx.h>
+#include <sys/stat.h>
+#include <fstream>
+#include <algorithm>
+
+using namespace std;
+
+#ifdef _WIN32
+# define TRANSFORM_DB_MODE 0
+#else
+# define TRANSFORM_DB_MODE (S_IRUSR | S_IWUSR)
+#endif
+
+static void
+usage(const char* n)
+{
+ cerr << "Usage: " << n << " [options] [dbenv db newdb]\n";
+ cerr <<
+ "Options:\n"
+ "-h, --help Show this message.\n"
+ "-v, --version Display the Ice version.\n"
+ "-DNAME Define NAME as 1.\n"
+ "-DNAME=DEF Define NAME as DEF.\n"
+ "-UNAME Remove any definition for NAME.\n"
+ "-IDIR Put DIR in the include file search path.\n"
+ "-d, --debug Print debug messages.\n"
+ "--ice Permit `Ice' prefix (for building Ice source code only)\n"
+ "-o FILE Output transformation descriptors into the file FILE.\n"
+ " Database transformation is not performed.\n"
+ "-i Ignore incompatible type changes.\n"
+ "-f FILE Execute the transformation descriptors in the file FILE.\n"
+ " Database transformation is not performed.\n"
+ "--old SLICE Load old Slice definitions from the file SLICE.\n"
+ "--new SLICE Load new Slice definitions from the file SLICE.\n"
+ "-e Indicates the database is an Evictor database.\n"
+ "--key TYPE[,TYPE] Specifies the Slice types of the database key. If the\n"
+ " type names have not changed, only one needs to be\n"
+ " specified. Otherwise, the type names are specified as\n"
+ " old-type,new-type.\n"
+ "--value TYPE[,TYPE] Specifies the Slice types of the database value. If the\n"
+ " type names have not changed, only one needs to be\n"
+ " specified. Otherwise, the type names are specified as\n"
+ " old-type,new-type.\n"
+ ;
+ // Note: --case-sensitive is intentionally not shown here!
+}
+
+static bool
+parseSlice(const string& n, const Slice::UnitPtr& u, const vector<string>& files, const string& cppArgs, bool debug)
+{
+ //
+ // Parse the Slice files.
+ //
+ for(vector<string>::const_iterator p = files.begin(); p != files.end(); ++p)
+ {
+ Slice::Preprocessor icecpp(n, *p, cppArgs);
+
+ FILE* cppHandle = icecpp.preprocess(false);
+
+ if(cppHandle == 0)
+ {
+ return false;
+ }
+
+ int status = u->parse(cppHandle, debug);
+
+ if(!icecpp.close())
+ {
+ return false;
+ }
+
+ if(status != EXIT_SUCCESS)
+ {
+ return false;
+ }
+ }
+
+ u->mergeModules();
+
+ return true;
+}
+
+static int
+run(int argc, char** argv, const Ice::CommunicatorPtr& communicator)
+{
+ string cppArgs;
+ vector<string> includePaths;
+ bool debug = false;
+ bool ice = false;
+ bool caseSensitive = false;
+ string outputFile;
+ bool ignoreTypeChanges = false;
+ string inputFile;
+ vector<string> oldSlice;
+ vector<string> newSlice;
+ bool evictor = false;
+ string keyTypeNames;
+ string valueTypeNames;
+ string dbEnvName, dbName, dbNameNew;
+
+ int idx = 1;
+ while(idx < argc)
+ {
+ if(strcmp(argv[idx], "-h") == 0 || strcmp(argv[idx], "--help") == 0)
+ {
+ usage(argv[0]);
+ return EXIT_SUCCESS;
+ }
+ else if(strcmp(argv[idx], "-v") == 0 || strcmp(argv[idx], "--version") == 0)
+ {
+ cout << ICE_STRING_VERSION << endl;
+ return EXIT_SUCCESS;
+ }
+ else if(strncmp(argv[idx], "-D", 2) == 0 || strncmp(argv[idx], "-U", 2) == 0)
+ {
+ cppArgs += ' ';
+ cppArgs += argv[idx];
+
+ for(int i = idx ; i + 1 < argc ; ++i)
+ {
+ argv[i] = argv[i + 1];
+ }
+ --argc;
+ }
+ else if(strncmp(argv[idx], "-I", 2) == 0)
+ {
+ cppArgs += ' ';
+ cppArgs += argv[idx];
+
+ string path = argv[idx] + 2;
+ if(path.length())
+ {
+ includePaths.push_back(path);
+ }
+
+ for(int i = idx ; i + 1 < argc ; ++i)
+ {
+ argv[i] = argv[i + 1];
+ }
+ --argc;
+ }
+ else if(strcmp(argv[idx], "-d") == 0 || strcmp(argv[idx], "--debug") == 0)
+ {
+ debug = true;
+ for(int i = idx ; i + 1 < argc ; ++i)
+ {
+ argv[i] = argv[i + 1];
+ }
+ --argc;
+ }
+ else if(strcmp(argv[idx], "--ice") == 0)
+ {
+ ice = true;
+ for(int i = idx ; i + 1 < argc ; ++i)
+ {
+ argv[i] = argv[i + 1];
+ }
+ --argc;
+ }
+ else if(strcmp(argv[idx], "--case-sensitive") == 0)
+ {
+ caseSensitive = true;
+ for(int i = idx ; i + 1 < argc ; ++i)
+ {
+ argv[i] = argv[i + 1];
+ }
+ --argc;
+ }
+ else if(strcmp(argv[idx], "-o") == 0)
+ {
+ if(idx + 1 >= argc || argv[idx + 1][0] == '-')
+ {
+ cerr << argv[0] << ": argument expected for `" << argv[idx] << "'" << endl;
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ outputFile = argv[idx + 1];
+
+ for(int i = idx ; i + 2 < argc ; ++i)
+ {
+ argv[i] = argv[i + 2];
+ }
+ argc -= 2;
+ }
+ else if(strcmp(argv[idx], "-i") == 0)
+ {
+ ignoreTypeChanges = true;
+ for(int i = idx ; i + 1 < argc ; ++i)
+ {
+ argv[i] = argv[i + 1];
+ }
+ --argc;
+ }
+ else if(strcmp(argv[idx], "-f") == 0)
+ {
+ if(idx + 1 >= argc || argv[idx + 1][0] == '-')
+ {
+ cerr << argv[0] << ": argument expected for `" << argv[idx] << "'" << endl;
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ inputFile = argv[idx + 1];
+
+ for(int i = idx ; i + 2 < argc ; ++i)
+ {
+ argv[i] = argv[i + 2];
+ }
+ argc -= 2;
+ }
+ else if(strcmp(argv[idx], "--old") == 0)
+ {
+ if(idx + 1 >= argc || argv[idx + 1][0] == '-')
+ {
+ cerr << argv[0] << ": argument expected for `" << argv[idx] << "'" << endl;
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ oldSlice.push_back(argv[idx + 1]);
+
+ for(int i = idx ; i + 2 < argc ; ++i)
+ {
+ argv[i] = argv[i + 2];
+ }
+ argc -= 2;
+ }
+ else if(strcmp(argv[idx], "--new") == 0)
+ {
+ if(idx + 1 >= argc || argv[idx + 1][0] == '-')
+ {
+ cerr << argv[0] << ": argument expected for `" << argv[idx] << "'" << endl;
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ newSlice.push_back(argv[idx + 1]);
+
+ for(int i = idx ; i + 2 < argc ; ++i)
+ {
+ argv[i] = argv[i + 2];
+ }
+ argc -= 2;
+ }
+ else if(strcmp(argv[idx], "-e") == 0)
+ {
+ evictor = true;
+ for(int i = idx ; i + 1 < argc ; ++i)
+ {
+ argv[i] = argv[i + 1];
+ }
+ --argc;
+ }
+ else if(strcmp(argv[idx], "--key") == 0)
+ {
+ if(idx + 1 >= argc || argv[idx + 1][0] == '-')
+ {
+ cerr << argv[0] << ": argument expected for `" << argv[idx] << "'" << endl;
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ keyTypeNames = argv[idx + 1];
+
+ for(int i = idx ; i + 2 < argc ; ++i)
+ {
+ argv[i] = argv[i + 2];
+ }
+ argc -= 2;
+ }
+ else if(strcmp(argv[idx], "--value") == 0)
+ {
+ if(idx + 1 >= argc || argv[idx + 1][0] == '-')
+ {
+ cerr << argv[0] << ": argument expected for `" << argv[idx] << "'" << endl;
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ valueTypeNames = argv[idx + 1];
+
+ for(int i = idx ; i + 2 < argc ; ++i)
+ {
+ argv[i] = argv[i + 2];
+ }
+ argc -= 2;
+ }
+ else if(argv[idx][0] == '-')
+ {
+ cerr << argv[0] << ": unknown option `" << argv[idx] << "'" << endl;
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+ else
+ {
+ ++idx;
+ }
+ }
+
+ if(outputFile.empty() && argc < 4)
+ {
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ if(argc > 1)
+ {
+ dbEnvName = argv[1];
+ }
+ if(argc > 2)
+ {
+ dbName = argv[2];
+ }
+ if(argc > 3)
+ {
+ dbNameNew = argv[3];
+ }
+
+ Slice::UnitPtr oldUnit = Slice::Unit::createUnit(true, false, ice, caseSensitive);
+ Transform::Destroyer<Slice::UnitPtr> oldD(oldUnit);
+ if(!parseSlice(argv[0], oldUnit, oldSlice, cppArgs, debug))
+ {
+ return EXIT_FAILURE;
+ }
+
+ Slice::UnitPtr newUnit = Slice::Unit::createUnit(true, false, ice, caseSensitive);
+ Transform::Destroyer<Slice::UnitPtr> newD(newUnit);
+ if(!parseSlice(argv[0], newUnit, newSlice, cppArgs, debug))
+ {
+ return EXIT_FAILURE;
+ }
+
+ //
+ // Create the Transformer.
+ //
+ Transform::Transformer transformer(communicator, oldUnit, newUnit, ignoreTypeChanges);
+
+ //
+ // If no input file was provided, then we need to analyze the Slice types.
+ //
+ string descriptors;
+ if(inputFile.empty())
+ {
+ ostringstream out;
+ vector<string> missingTypes;
+ vector<string> analyzeErrors;
+
+ if(evictor)
+ {
+ transformer.analyze(out, missingTypes, analyzeErrors);
+ }
+ else
+ {
+ string oldKeyName, newKeyName, oldValueName, newValueName;
+ string::size_type pos;
+
+ if(keyTypeNames.empty() || valueTypeNames.empty())
+ {
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ pos = keyTypeNames.find(',');
+ if(pos == 0 || pos == keyTypeNames.size())
+ {
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+ if(pos == string::npos)
+ {
+ oldKeyName = keyTypeNames;
+ newKeyName = keyTypeNames;
+ }
+ else
+ {
+ oldKeyName = keyTypeNames.substr(0, pos);
+ newKeyName = keyTypeNames.substr(pos + 1);
+ }
+
+ pos = valueTypeNames.find(',');
+ if(pos == 0 || pos == valueTypeNames.size())
+ {
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+ if(pos == string::npos)
+ {
+ oldValueName = valueTypeNames;
+ newValueName = valueTypeNames;
+ }
+ else
+ {
+ oldValueName = valueTypeNames.substr(0, pos);
+ newValueName = valueTypeNames.substr(pos + 1);
+ }
+
+ transformer.analyze(oldKeyName, newKeyName, oldValueName, newValueName, out, missingTypes, analyzeErrors);
+ }
+
+ if(!analyzeErrors.empty())
+ {
+ for(vector<string>::const_iterator p = analyzeErrors.begin(); p != analyzeErrors.end(); ++p)
+ {
+ cerr << argv[0] << ": " << *p << endl;
+ }
+ }
+
+ if(!missingTypes.empty())
+ {
+ sort(missingTypes.begin(), missingTypes.end());
+ unique(missingTypes.begin(), missingTypes.end());
+ if(!analyzeErrors.empty())
+ {
+ cerr << endl;
+ }
+ cerr << "The following types had no matching definitions in the new Slice:" << endl;
+ for(vector<string>::const_iterator p = missingTypes.begin(); p != missingTypes.end(); ++p)
+ {
+ cerr << *p << endl;
+ }
+ }
+
+ if(!analyzeErrors.empty())
+ {
+ return EXIT_FAILURE;
+ }
+
+ descriptors = out.str();
+
+ if(!outputFile.empty())
+ {
+ ofstream of(outputFile.c_str());
+ if(!of.good())
+ {
+ cerr << argv[0] << ": unable to open file `" << outputFile << "'" << endl;
+ return EXIT_FAILURE;
+ }
+ of << descriptors;
+ of.close();
+ return EXIT_SUCCESS;
+ }
+ }
+ else
+ {
+ ifstream in(inputFile.c_str());
+ char buff[1024];
+ while(true)
+ {
+ in.read(buff, 1024);
+ descriptors.append(buff, in.gcount());
+ if(in.gcount() < 1024)
+ {
+ break;
+ }
+ }
+ in.close();
+ }
+
+ DbEnv dbEnv(0);
+ Db* db = 0;
+ Db* dbNew = 0;
+ int status = EXIT_SUCCESS;
+ try
+ {
+#ifdef _WIN32
+ //
+ // Berkeley DB may use a different C++ runtime.
+ //
+ dbEnv.set_alloc(::malloc, ::realloc, ::free);
+#endif
+
+ u_int32_t flags = DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN | DB_RECOVER | DB_CREATE;
+ dbEnv.open(dbEnvName.c_str(), flags, TRANSFORM_DB_MODE);
+ db = new Db(&dbEnv, 0);
+ db->open(0, dbName.c_str(), 0, DB_BTREE, DB_RDONLY, TRANSFORM_DB_MODE);
+ dbNew = new Db(&dbEnv, 0);
+ dbNew->open(0, dbNameNew.c_str(), 0, DB_BTREE, DB_CREATE | DB_TRUNCATE, TRANSFORM_DB_MODE);
+
+ istringstream istr(descriptors);
+ transformer.transform(istr, db, dbNew, cerr);
+ }
+ catch(const DbException& ex)
+ {
+ cerr << argv[0] << ": database error: " << ex.what() << endl;
+ status = EXIT_FAILURE;
+ }
+ catch(...)
+ {
+ if(db)
+ {
+ db->close(0);
+ delete db;
+ }
+ if(dbNew)
+ {
+ dbNew->close(0);
+ delete dbNew;
+ }
+ dbEnv.close(0);
+ throw;
+ }
+
+ if(db)
+ {
+ db->close(0);
+ delete db;
+ }
+ if(dbNew)
+ {
+ dbNew->close(0);
+ delete dbNew;
+ }
+ dbEnv.close(0);
+
+ return status;
+}
+
+int
+main(int argc, char* argv[])
+{
+ Ice::CommunicatorPtr communicator;
+ int status = EXIT_SUCCESS;
+ try
+ {
+ communicator = Ice::initialize(argc, argv);
+ status = run(argc, argv, communicator);
+ }
+ catch(const Transform::TransformException& ex)
+ {
+ cerr << ex.reason();
+ return EXIT_FAILURE;
+ }
+ catch(const IceUtil::Exception& ex)
+ {
+ cerr << argv[0] << ": " << ex << endl;
+ return EXIT_FAILURE;
+ }
+
+ if(communicator)
+ {
+ communicator->destroy();
+ }
+
+ return status;
+}