int main(int argc, char* argv[]) { int status = EXIT_SUCCESS; Ice::CommunicatorPtr communicator; string envName = "db"; communicator = Ice::initialize(argc, argv); if(argc != 1) { envName = argv[1]; envName += "/db"; } { Freeze::ConnectionPtr connection; try { connection = Freeze::createConnection(communicator, envName); test(true); } catch(const exception& ex) { cerr << "excetpion:\n" << ex.what() << endl; test(false); } catch(...) { test(false); } cout << "File lock acquired.\n" << "Enter some input and press enter, to release the lock and terminate the program." << endl; // // Block the test waiting for IO, so the file lock is preserved. // string foo; cin >> foo; // // Clean up. // if(connection) { connection->close(); } } cout << "File lock released." << endl; try { communicator->destroy(); } catch(const Ice::Exception& ex) { cerr << ex << endl; status = EXIT_FAILURE; } return status; }
static int run(const Ice::StringSeq& originalArgs, const Ice::CommunicatorPtr& communicator) { vector<string> oldCppArgs; vector<string> newCppArgs; bool debug; bool ice = true; // Needs to be true in order to create default definitions. bool underscore; string outputFile; bool ignoreTypeChanges; bool purgeObjects; bool catastrophicRecover; bool suppress; string inputFile; vector<string> oldSlice; vector<string> newSlice; bool evictor; string keyTypeNames; string valueTypeNames; string dbEnvName, dbName, dbEnvNameNew; bool allDb = false; IceUtilInternal::Options opts; opts.addOpt("h", "help"); opts.addOpt("v", "version"); opts.addOpt("D", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); opts.addOpt("U", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); opts.addOpt("d", "debug"); opts.addOpt("", "underscore"); opts.addOpt("o", "", IceUtilInternal::Options::NeedArg); opts.addOpt("i"); opts.addOpt("p"); opts.addOpt("c"); opts.addOpt("w"); opts.addOpt("f", "", IceUtilInternal::Options::NeedArg); opts.addOpt("", "include-old", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); opts.addOpt("", "include-new", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); opts.addOpt("", "old", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); opts.addOpt("", "new", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); opts.addOpt("a"); opts.addOpt("e"); opts.addOpt("", "key", IceUtilInternal::Options::NeedArg); opts.addOpt("", "value", IceUtilInternal::Options::NeedArg); const string appName = originalArgs[0]; vector<string> args; try { args = opts.parse(originalArgs); } catch(const IceUtilInternal::BadOptException& e) { cerr << appName << ": " << e.reason << endl; usage(appName); return EXIT_FAILURE; } if(opts.isSet("help")) { usage(appName); return EXIT_SUCCESS; } if(opts.isSet("version")) { cout << ICE_STRING_VERSION << endl; return EXIT_SUCCESS; } if(opts.isSet("D")) { vector<string> optargs = opts.argVec("D"); for(vector<string>::const_iterator i = optargs.begin(); i != optargs.end(); ++i) { oldCppArgs.push_back("-D" + *i); newCppArgs.push_back("-D" + *i); } } if(opts.isSet("U")) { vector<string> optargs = opts.argVec("U"); for(vector<string>::const_iterator i = optargs.begin(); i != optargs.end(); ++i) { oldCppArgs.push_back("-U" + *i); newCppArgs.push_back("-U" + *i); } } debug = opts.isSet("debug"); underscore = opts.isSet("underscore"); if(opts.isSet("o")) { outputFile = opts.optArg("o"); } ignoreTypeChanges = opts.isSet("i"); purgeObjects = opts.isSet("p"); catastrophicRecover = opts.isSet("c"); suppress = opts.isSet("w"); if(opts.isSet("f")) { inputFile = opts.optArg("f"); } if(opts.isSet("include-old")) { vector<string> optargs = opts.argVec("include-old"); for(vector<string>::const_iterator i = optargs.begin(); i != optargs.end(); ++i) { oldCppArgs.push_back("-I" + *i); } } if(opts.isSet("include-new")) { vector<string> optargs = opts.argVec("include-new"); for(vector<string>::const_iterator i = optargs.begin(); i != optargs.end(); ++i) { newCppArgs.push_back("-I" + *i); } } if(opts.isSet("old")) { vector<string> optargs = opts.argVec("old"); for(vector<string>::const_iterator i = optargs.begin(); i != optargs.end(); ++i) { oldSlice.push_back(*i); } } if(opts.isSet("new")) { vector<string> optargs = opts.argVec("new"); for(vector<string>::const_iterator i = optargs.begin(); i != optargs.end(); ++i) { newSlice.push_back(*i); } } evictor = opts.isSet("e"); if(opts.isSet("key")) { keyTypeNames = opts.optArg("key"); } if(opts.isSet("value")) { valueTypeNames = opts.optArg("value"); } if(outputFile.empty()) { if(args.size() == 2) { allDb = true; } else if(args.size() != 3) { usage(appName); return EXIT_FAILURE; } } else { if(args.size() == 1) { allDb = true; } else if(args.size() != 0) { usage(appName); return EXIT_FAILURE; } } if(allDb && (!keyTypeNames.empty() || !valueTypeNames.empty())) { usage(appName); return EXIT_FAILURE; } if(inputFile.empty() && !allDb && !evictor && (keyTypeNames.empty() || valueTypeNames.empty())) { usage(appName); return EXIT_FAILURE; } if(args.size() > 0) { dbEnvName = args[0]; } if(args.size() > 1) { if(allDb) { dbEnvNameNew = args[1]; } else { dbName = args[1]; } } if(args.size() > 2) { dbEnvNameNew = args[2]; } if(args.size() > 3) { cerr << appName << ": too many arguments" << endl; usage(appName); return EXIT_FAILURE; } // // Freeze creates a lock file by default to prevent multiple processes from opening // the same database environment simultaneously. In the case of a read-only program // such as transformdb, however, we still want to be able to open the environment despite // the lock. This assumes of course that the other process has opened the environment // with DbPrivate=0. If DbPrivate=0 is also set for dumpdb, we disable the lock. // if(!catastrophicRecover && outputFile.empty()) { Ice::PropertiesPtr props = communicator->getProperties(); string prefix = "Freeze.DbEnv." + args[0]; if(props->getPropertyAsIntWithDefault(prefix + ".DbPrivate", 1) == 0) { props->setProperty(prefix + ".LockFile", "0"); } } Slice::UnitPtr oldUnit = Slice::Unit::createUnit(true, true, ice, underscore); FreezeScript::Destroyer<Slice::UnitPtr> oldD(oldUnit); if(!FreezeScript::parseSlice(appName, oldUnit, oldSlice, oldCppArgs, debug, "-D__TRANSFORMDB__")) { return EXIT_FAILURE; } Slice::UnitPtr newUnit = Slice::Unit::createUnit(true, true, ice, underscore); FreezeScript::Destroyer<Slice::UnitPtr> newD(newUnit); if(!FreezeScript::parseSlice(appName, newUnit, newSlice, newCppArgs, debug, "-D__TRANSFORMDB__")) { return EXIT_FAILURE; } // // Install the evictor types in the Slice units. // FreezeScript::createEvictorSliceTypes(oldUnit); FreezeScript::createEvictorSliceTypes(newUnit); // // Read the catalog if necessary. // FreezeScript::CatalogDataMap catalog; if(allDb) { try { catalog = FreezeScript::readCatalog(communicator, dbEnvName); } catch(const FreezeScript::FailureException& ex) { cerr << appName << ": " << ex.reason() << endl; return EXIT_FAILURE; } if(catalog.empty()) { cerr << appName << ": no databases in environment `" << dbEnvName << "'" << endl; return EXIT_FAILURE; } } // // 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; FreezeScript::TransformAnalyzer analyzer(oldUnit, newUnit, ignoreTypeChanges, out, missingTypes, analyzeErrors); const string evictorKeyName = "::Ice::Identity"; const string oldEvictorValueName = "::Freeze::ObjectRecord"; const string newEvictorValueName = "Object"; if(allDb) { // // Add a <database> element for each database in the catalog. // for(FreezeScript::CatalogDataMap::iterator p = catalog.begin(); p != catalog.end(); ++p) { string keyName, valueName; if(p->second.evictor) { keyName = p->second.key; valueName = p->second.value; if(keyName.empty()) { keyName = evictorKeyName; } if(valueName.empty()) { valueName = oldEvictorValueName; } } else { keyName = p->second.key; valueName = p->second.value; } // // Look up the key and value types in the old and new Slice definitions. // Slice::TypePtr oldKeyType = findType(oldUnit, keyName); if(!oldKeyType) { cerr << appName << ": type `" << keyName << "' from database `" << p->first << "' not found in old Slice definitions" << endl; } Slice::TypePtr newKeyType = findType(newUnit, keyName); if(!newKeyType) { cerr << appName << ": type `" << keyName << "' from database `" << p->first << "' not found in new Slice definitions" << endl; } Slice::TypePtr oldValueType = findType(oldUnit, valueName); if(!oldValueType) { cerr << appName << ": type `" << valueName << "' from database `" << p->first << "' not found in old Slice definitions" << endl; } Slice::TypePtr newValueType; if(p->second.evictor) { // // The new evictor does not keep stats // newValueType = findType(newUnit, newEvictorValueName); } else { newValueType = findType(newUnit, valueName); } if(!newValueType) { cerr << appName << ": type `" << valueName << "' from database `" << p->first << "' not found in new Slice definitions" << endl; } // // If we are generating an output file, we do not consider a missing type to be // an error. Since the type information comes from the catalog of the old // environment, it's possible that the key or value types are not present in // the new Slice definitions. Rather than abort at this point, we simply emit // a partially-defined <database> element that must be edited by the user. // // If we are not generating an output file, we have to stop now. // if(outputFile.empty() && (!oldKeyType || !newKeyType || !oldValueType || !newValueType)) { return EXIT_FAILURE; } analyzer.addDatabase(p->first, oldKeyType, newKeyType, oldValueType, newValueType); } } else { string oldKeyName, newKeyName, oldValueName, newValueName; string::size_type pos; if(!evictor && (keyTypeNames.empty() || valueTypeNames.empty())) { usage(appName); return EXIT_FAILURE; } if(!keyTypeNames.empty()) { pos = keyTypeNames.find(','); if(pos == 0 || pos == keyTypeNames.size()) { usage(appName); return EXIT_FAILURE; } if(pos == string::npos) { oldKeyName = keyTypeNames; newKeyName = keyTypeNames; } else { oldKeyName = keyTypeNames.substr(0, pos); newKeyName = keyTypeNames.substr(pos + 1); } } if(!valueTypeNames.empty()) { pos = valueTypeNames.find(','); if(pos == 0 || pos == valueTypeNames.size()) { usage(appName); return EXIT_FAILURE; } if(pos == string::npos) { oldValueName = valueTypeNames; newValueName = valueTypeNames; } else { oldValueName = valueTypeNames.substr(0, pos); newValueName = valueTypeNames.substr(pos + 1); } } if(evictor) { if(oldKeyName.empty()) { oldKeyName = evictorKeyName; } if(newKeyName.empty()) { newKeyName = evictorKeyName; } if(oldValueName.empty()) { oldValueName = newEvictorValueName; } if(newValueName.empty()) { newValueName = newEvictorValueName; } } // // Look up the key and value types in the old and new Slice definitions. // Slice::TypePtr oldKeyType = findType(oldUnit, oldKeyName); if(!oldKeyType) { cerr << appName << ": type `" << oldKeyName << "' not found in old Slice definitions" << endl; } Slice::TypePtr newKeyType = findType(newUnit, newKeyName); if(!newKeyType) { cerr << appName << ": type `" << newKeyName << "' not found in new Slice definitions" << endl; } Slice::TypePtr oldValueType = findType(oldUnit, oldValueName); if(!oldValueType) { cerr << appName << ": type `" << oldValueName << "' not found in old Slice definitions" << endl; } Slice::TypePtr newValueType = findType(newUnit, newValueName); if(!newValueType) { cerr << appName << ": type `" << newValueName << "' not found in new Slice definitions" << endl; } // // Stop now if any of the types could not be found. // if(!oldKeyType || !newKeyType || !oldValueType || !newValueType) { return EXIT_FAILURE; } analyzer.addDatabase("", oldKeyType, newKeyType, oldValueType, newValueType); } analyzer.finish(); if(!analyzeErrors.empty()) { for(vector<string>::const_iterator p = analyzeErrors.begin(); p != analyzeErrors.end(); ++p) { cerr << appName << ": " << *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()) { // // No nativeToUTF8 conversion necessary here, no string converter is installed // by wmain() on Windows and args are assumbed to be UTF8 on Unix platforms. // IceUtilInternal::ofstream of(outputFile); if(!of.good()) { cerr << appName << ": unable to open file `" << outputFile << "'" << endl; return EXIT_FAILURE; } of << descriptors; of.close(); return EXIT_SUCCESS; } } else { // // Read the input file. // // No nativeToUTF8 conversion necessary here, no string converter is installed // by wmain() on Windows and args are assumbed to be UTF8 on Unix platforms. // IceUtilInternal::ifstream in(inputFile); char buff[1024]; while(true) { in.read(buff, 1024); descriptors.append(buff, static_cast<size_t>(in.gcount())); if(in.gcount() < 1024) { break; } } in.close(); } if(dbEnvName == dbEnvNameNew) { cerr << appName << ": database environment names must be different" << endl; return EXIT_FAILURE; } FreezeScript::ObjectFactoryPtr objectFactory = new FreezeScript::ObjectFactory; communicator->addObjectFactory(objectFactory, ""); // // Transform the database. // DbEnv dbEnv(0); DbEnv dbEnvNew(0); Freeze::TransactionPtr txNew; Freeze::ConnectionPtr connection; Freeze::ConnectionPtr connectionNew; vector<Db*> dbs; int status = EXIT_SUCCESS; try { #ifdef _WIN32 // // Berkeley DB may use a different C++ runtime. // dbEnv.set_alloc(::malloc, ::realloc, ::free); dbEnvNew.set_alloc(::malloc, ::realloc, ::free); #endif // // Open the old database environment. Use DB_RECOVER_FATAL if -c is specified. // No transaction is created for the old environment. // // DB_THREAD is for compatibility with Freeze (the catalog) // { u_int32_t flags = DB_THREAD | DB_CREATE | DB_INIT_TXN | DB_INIT_MPOOL; if(catastrophicRecover) { flags |= DB_INIT_LOG | DB_RECOVER_FATAL; } dbEnv.open(dbEnvName.c_str(), flags, FREEZE_SCRIPT_DB_MODE); } // // We're creating a connection just to make sure the database environment // isn't locked. // connection = Freeze::createConnection(communicator, dbEnvName, dbEnv); // // Open the new database environment and start a transaction. // // // DB_THREAD is for compatibility with Freeze (the catalog) // { u_int32_t flags = DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN | DB_RECOVER | DB_CREATE | DB_THREAD; dbEnvNew.open(dbEnvNameNew.c_str(), flags, FREEZE_SCRIPT_DB_MODE); } // // TODO: handle properly DbHome config (currently it will break if it's set for the new env) // // // Open the catalog of the new environment, and start a transaction. // connectionNew = Freeze::createConnection(communicator, dbEnvNameNew, dbEnvNew); txNew = connectionNew->beginTransaction(); DbTxn* txnNew = Freeze::getTxn(txNew); if(allDb) { // // Transform all databases in the old catalog. // for(FreezeScript::CatalogDataMap::iterator p = catalog.begin(); p != catalog.end(); ++p) { transformDb(p->second.evictor, communicator, objectFactory, dbEnv, dbEnvNew, p->first, connectionNew, dbs, oldUnit, newUnit, txnNew, purgeObjects, suppress, descriptors); } } else { transformDb(evictor, communicator, objectFactory, dbEnv, dbEnvNew, dbName, connectionNew, dbs, oldUnit, newUnit, txnNew, purgeObjects, suppress, descriptors); } } catch(const DbException& ex) { cerr << appName << ": database error: " << ex.what() << endl; status = EXIT_FAILURE; } catch(const IceUtil::FileLockException&) { cerr << appName << ": error: database environment is locked" << endl; status = EXIT_FAILURE; } catch(...) { try { if(txNew != 0) { txNew->rollback(); txNew = 0; } if(connectionNew) { connectionNew->close(); connectionNew = 0; } if(connection) { connection->close(); connection = 0; } for(vector<Db*>::iterator p = dbs.begin(); p != dbs.end(); ++p) { Db* db = *p; db->close(0); delete db; } try { dbEnv.close(0); } catch(const DbException&) { } try { dbEnvNew.close(0); } catch(const DbException&) { } } catch(const DbException& ex) { cerr << appName << ": database error: " << ex.what() << endl; } throw; } if(txNew != 0) { try { if(status == EXIT_FAILURE) { txNew->rollback(); } else { txNew->commit(); // // Checkpoint to migrate changes from the log to the database(s). // dbEnvNew.txn_checkpoint(0, 0, DB_FORCE); } for(vector<Db*>::iterator p = dbs.begin(); p != dbs.end(); ++p) { Db* db = *p; db->close(0); delete db; } } catch(const DbException& ex) { cerr << appName << ": database error: " << ex.what() << endl; status = EXIT_FAILURE; } } // Clear the transaction before closing the database environment. txNew = 0; if(connectionNew) { connectionNew->close(); connectionNew = 0; } if(connection) { connection->close(); connection = 0; } try { dbEnv.close(0); } catch(const DbException&) { } try { dbEnvNew.close(0); } catch(const DbException&) { } return status; }
int main(int argc, char* argv[]) { int status; Ice::CommunicatorPtr communicator; string envName = "db"; try { communicator = Ice::initialize(argc, argv); if(argc != 1) { envName = argv[1]; envName += "/"; envName += "db"; } status = run(communicator, envName); } catch(const Ice::Exception& ex) { cerr << ex << endl; status = EXIT_FAILURE; } cout << "testing manual code... " << flush; // // From manual // Freeze::ConnectionPtr connection = Freeze::createConnection(communicator, envName); // Instantiate the map. // ByteIntMap map(connection, "simple"); // Clear the map. // map.clear(); Ice::Int i; ByteIntMap::iterator p; // Populate the map. // for (i = 0; i < 26; i++) { Ice::Byte key = static_cast<Ice::Byte>('a' + i); map.insert(pair<const Byte, const int>(key, i)); } // Iterate over the map and change the values. // for (p = map.begin(); p != map.end(); ++p) { p.set(p->second + 1); } // Find and erase the last element. // p = map.find(static_cast<Ice::Byte>('z')); assert(p != map.end()); map.erase(p); // Clean up. // connection->close(); cout << "ok" << endl; try { communicator->destroy(); } catch(const Ice::Exception& ex) { cerr << ex << endl; status = EXIT_FAILURE; } return status; }
static int run(const Ice::StringSeq& originalArgs, const Ice::CommunicatorPtr& communicator, const FreezeScript::CompactIdResolverIPtr& resolver) { vector<string> cppArgs; bool debug; bool ice = true; // Needs to be true in order to create default definitions. bool underscore; string outputFile; string inputFile; vector<string> slice; bool evictor; string keyTypeName; string valueTypeName; string selectExpr; string dbEnvName, dbName; const string appName = originalArgs[0]; IceUtilInternal::Options opts; opts.addOpt("h", "help"); opts.addOpt("v", "version"); opts.addOpt("D", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); opts.addOpt("U", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); opts.addOpt("I", "", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); opts.addOpt("d", "debug"); opts.addOpt("", "ice"); opts.addOpt("", "underscore"); opts.addOpt("o", "", IceUtilInternal::Options::NeedArg); opts.addOpt("f", "", IceUtilInternal::Options::NeedArg); opts.addOpt("", "load", IceUtilInternal::Options::NeedArg, "", IceUtilInternal::Options::Repeat); opts.addOpt("e"); opts.addOpt("", "key", IceUtilInternal::Options::NeedArg); opts.addOpt("", "value", IceUtilInternal::Options::NeedArg); opts.addOpt("", "select", IceUtilInternal::Options::NeedArg); opts.addOpt("c", "catalog"); vector<string> args; try { args = opts.parse(originalArgs); } catch(const IceUtilInternal::BadOptException& e) { cerr << appName << ": " << e.reason << endl; usage(appName); return EXIT_FAILURE; } // // Freeze creates a lock file by default to prevent multiple processes from opening // the same database environment simultaneously. In the case of a read-only program // such as dumpdb, however, we still want to be able to open the environment despite // the lock. This assumes of course that the other process has opened the environment // with DbPrivate=0. If DbPrivate=0 is also set for dumpdb, we disable the lock. // if(!args.empty()) { // // If an argument is present, we assume it is the name of the database environment. // Ice::PropertiesPtr props = communicator->getProperties(); string prefix = "Freeze.DbEnv." + args[0]; if(props->getPropertyAsIntWithDefault(prefix + ".DbPrivate", 1) <= 0) { props->setProperty(prefix + ".LockFile", "0"); } } if(opts.isSet("h")) { usage(appName); return EXIT_SUCCESS; } if(opts.isSet("version")) { cout << ICE_STRING_VERSION << endl; return EXIT_SUCCESS; } if(opts.isSet("c")) { if(args.empty()) { cerr << appName << ": no database environment specified." << endl; usage(appName); return EXIT_FAILURE; } else if(args.size() > 2) { usage(appName); return EXIT_FAILURE; } try { FreezeScript::CatalogDataMap catalog = FreezeScript::readCatalog(communicator, args[0]); if(args.size() == 1) { if(catalog.empty()) { cout << "Catalog is empty." << endl; } else { cout << "Catalog contents:" << endl; for(FreezeScript::CatalogDataMap::const_iterator p = catalog.begin(); p != catalog.end(); ++p) { cout << endl; printCatalogData(p->first, p->second); } } } else { FreezeScript::CatalogDataMap::const_iterator p = catalog.find(args[1]); if(p == catalog.end()) { cerr << appName << ": database `" << args[1] << "' not found in environment `" << args[0] << "'." << endl; return EXIT_FAILURE; } else { printCatalogData(p->first, p->second); } } return EXIT_SUCCESS; } catch(const FreezeScript::FailureException& ex) { cerr << appName << ": " << ex.reason() << endl; return EXIT_FAILURE; } } if(opts.isSet("D")) { vector<string> optargs = opts.argVec("D"); for(vector<string>::const_iterator i = optargs.begin(); i != optargs.end(); ++i) { cppArgs.push_back("-D" + *i); } } if(opts.isSet("U")) { vector<string> optargs = opts.argVec("U"); for(vector<string>::const_iterator i = optargs.begin(); i != optargs.end(); ++i) { cppArgs.push_back("-U" + *i); } } if(opts.isSet("I")) { vector<string> optargs = opts.argVec("I"); for(vector<string>::const_iterator i = optargs.begin(); i != optargs.end(); ++i) { cppArgs.push_back("-I" + *i); } } debug = opts.isSet("debug"); // No need to set --ice option here -- it is always true. underscore = opts.isSet("underscore"); if(opts.isSet("o")) { outputFile = opts.optArg("o"); } if(opts.isSet("f")) { inputFile = opts.optArg("f"); } if(opts.isSet("load")) { vector<string> optArgs = opts.argVec("load"); for(vector<string>::const_iterator i = optArgs.begin(); i != optArgs.end(); ++i) { slice.push_back(*i); } } evictor = opts.isSet("e"); if(opts.isSet("key")) { keyTypeName = opts.optArg("key"); } if(opts.isSet("value")) { valueTypeName = opts.optArg("value"); } if(opts.isSet("select")) { selectExpr = opts.optArg("select"); } if(outputFile.empty() && args.size() != 2) { usage(appName); return EXIT_FAILURE; } if(!args.empty()) { dbEnvName = args[0]; } if(args.size() == 2) { dbName = args[1]; } else { usage(appName); return EXIT_FAILURE; } if(!inputFile.empty() && !selectExpr.empty()) { cerr << appName << ": an input file cannot be specified with --select" << endl; return EXIT_FAILURE; } Slice::UnitPtr unit = Slice::Unit::createUnit(true, true, ice, underscore); FreezeScript::Destroyer<Slice::UnitPtr> unitD(unit); if(!FreezeScript::parseSlice(appName, unit, slice, cppArgs, debug, "-D__DUMPDB__")) { return EXIT_FAILURE; } FreezeScript::createEvictorSliceTypes(unit); FreezeScript::collectCompactIds(unit, resolver); // // If no input file was provided, then we need to generate default descriptors. // string descriptors; if(inputFile.empty()) { const string evictorKeyTypeName = "::Ice::Identity"; const string oldEvictorValueTypeName = "::Freeze::ObjectRecord"; const string newEvictorValueTypeName = "Object"; if((!keyTypeName.empty() && valueTypeName.empty()) || (keyTypeName.empty() && !valueTypeName.empty() && !evictor)) { cerr << appName << ": a key type and a value type must be specified" << endl; usage(appName); return EXIT_FAILURE; } else if(valueTypeName.empty()) { try { FreezeScript::CatalogDataMap catalog = FreezeScript::readCatalog(communicator, dbEnvName); FreezeScript::CatalogDataMap::iterator p = catalog.find(dbName); if(p == catalog.end()) { cerr << appName << ": database `" << dbName << "' not found in catalog." << endl; cerr << "Current catalog databases:" << endl; for(p = catalog.begin(); p != catalog.end(); ++p) { cerr << " " << p->first << endl; } return EXIT_FAILURE; } else { if(p->second.evictor) { evictor = true; } keyTypeName = p->second.key; valueTypeName = p->second.value; if(evictor && valueTypeName.empty()) { valueTypeName = oldEvictorValueTypeName; } } } catch(const FreezeScript::FailureException& ex) { cerr << appName << ": " << ex.reason() << endl; return EXIT_FAILURE; } } if(evictor) { if(keyTypeName.empty()) { keyTypeName = evictorKeyTypeName; } if(valueTypeName.empty()) { valueTypeName = newEvictorValueTypeName; } } Slice::TypePtr keyType, valueType; Slice::TypeList l; l = unit->lookupType(keyTypeName, false); if(l.empty()) { cerr << appName << ": unknown key type `" << keyTypeName << "'" << endl; return EXIT_FAILURE; } keyType = l.front(); l = unit->lookupType(valueTypeName, false); if(l.empty()) { cerr << appName << ": unknown value type `" << valueTypeName << "'" << endl; return EXIT_FAILURE; } valueType = l.front(); ostringstream os; IceUtilInternal::XMLOutput out(os); out << se("dumpdb"); FreezeScript::SliceVisitor visitor(out, keyType, valueType, selectExpr); unit->visit(&visitor, false); out << ee; descriptors = os.str(); if(!outputFile.empty()) { IceUtilInternal::ofstream of(outputFile); if(!of.good()) { cerr << appName << ": unable to open file `" << outputFile << "'" << endl; return EXIT_FAILURE; } of << descriptors << endl; of.close(); return EXIT_SUCCESS; } } else { IceUtilInternal::ifstream in(inputFile); char buff[1024]; while(true) { in.read(buff, 1024); descriptors.append(buff, static_cast<size_t>(in.gcount())); if(in.gcount() < 1024) { break; } } in.close(); } FreezeScript::ValueFactoryPtr valueFactory = new FreezeScript::ValueFactory; communicator->getValueFactoryManager()->add(valueFactory, ""); DbEnv dbEnv(0); DbTxn* txn = 0; Freeze::ConnectionPtr connection; int status = EXIT_SUCCESS; try { #ifdef _WIN32 // // Berkeley DB may use a different C++ runtime. // dbEnv.set_alloc(::malloc, ::realloc, ::free); #endif // // Open the database environment and start a transaction. // { u_int32_t flags = DB_THREAD | DB_CREATE | DB_INIT_TXN | DB_INIT_MPOOL; dbEnv.open(dbEnvName.c_str(), flags, FREEZE_SCRIPT_DB_MODE); } // // We're creating a connection just to make sure the database environment // isn't locked. // connection = Freeze::createConnection(communicator, dbEnvName, dbEnv); dbEnv.txn_begin(0, &txn, 0); FreezeScript::ErrorReporterPtr errorReporter = new FreezeScript::ErrorReporter(cerr, false); try { FreezeScript::DataFactoryPtr factory = new FreezeScript::DataFactory(communicator, unit, errorReporter); FreezeScript::DescriptorHandler dh(factory, unit, errorReporter, valueFactory); istringstream istr(descriptors); IceXML::Parser::parse(istr, dh); FreezeScript::DumpDBDescriptorPtr descriptor = dh.descriptor(); descriptor->validate(); if(evictor) { // // The evictor database file contains multiple databases. We must first // determine the names of those databases, ignoring any whose names // begin with "$index:". Each database represents a separate facet, with // the facet name used as the database name. The database named "$default" // represents the main object. // vector<string> dbNames; { Db db(&dbEnv, 0); db.open(txn, dbName.c_str(), 0, DB_UNKNOWN, DB_RDONLY, 0); Dbt dbKey, dbValue; dbKey.set_flags(DB_DBT_MALLOC); dbValue.set_flags(DB_DBT_USERMEM | DB_DBT_PARTIAL); Dbc* dbc = 0; db.cursor(txn, &dbc, 0); while(dbc->get(&dbKey, &dbValue, DB_NEXT) == 0) { string s(static_cast<char*>(dbKey.get_data()), dbKey.get_size()); if(s.find("$index:") != 0) { dbNames.push_back(s); } free(dbKey.get_data()); } dbc->close(); db.close(0); } // // Dump each database. // for(vector<string>::iterator p = dbNames.begin(); p != dbNames.end(); ++p) { string name = *p; string facet = (name == "$default" ? string("") : name); Db db(&dbEnv, 0); db.open(txn, dbName.c_str(), name.c_str(), DB_BTREE, DB_RDONLY, FREEZE_SCRIPT_DB_MODE); descriptor->dump(communicator, &db, txn, facet); db.close(0); } } else { // // Dump a map database. // Db db(&dbEnv, 0); db.open(txn, dbName.c_str(), 0, DB_BTREE, DB_RDONLY, FREEZE_SCRIPT_DB_MODE); descriptor->dump(communicator, &db, txn, ""); db.close(0); } } catch(const IceXML::ParserException& ex) { errorReporter->error(ex.reason()); } } catch(const DbException& ex) { cerr << appName << ": database error: " << ex.what() << endl; status = EXIT_FAILURE; } catch(...) { try { if(txn) { txn->abort(); } dbEnv.close(0); } catch(const DbException& ex) { cerr << appName << ": database error: " << ex.what() << endl; } if(connection) { connection->close(); connection = 0; } throw; } try { if(txn) { txn->abort(); } if(connection) { connection->close(); } dbEnv.close(0); } catch(const DbException& ex) { cerr << appName << ": database error: " << ex.what() << endl; status = EXIT_FAILURE; } return status; }
int main(int argc, char* argv[]) { Ice::InitializationData initData; initData.properties = Ice::createProperties(); initData.properties->load("config"); Ice::CommunicatorPtr communicator = Ice::initialize(argc, argv, initData); if(argc > 1) { cerr << argv[0] << ": too many arguments" << endl; return EXIT_FAILURE; } Freeze::ConnectionPtr connection = Freeze::createConnection(communicator, "backup"); IntLongMap m(connection, "IntLongMap", true); const int size = 10000; if(m.size() == 0) { cout << "********* Creating new map ***********" << endl; Freeze::TransactionHolder txHolder(connection); IceUtil::Time time = IceUtil::Time::now(); IceUtil::Int64 ms = time.toMilliSeconds(); for(int i = 0; i < size; ++i) { m.insert(IntLongMap::value_type(i, ms)); } txHolder.commit(); } cout << "Updating map" << endl; for(;;) { int count = 0; Freeze::TransactionHolder txHolder(connection); IceUtil::Time time = IceUtil::Time::now(); IceUtil::Int64 ms = time.toMilliSeconds(); IntLongMap::iterator p = m.begin(); IceUtil::Int64 oldMs = p->second; do { if(p->second != oldMs) { cerr << "old time (ms) == " << oldMs << endl; cerr << "current current (ms) == " << p->second << endl; } test(p->second == oldMs); p.set(ms); count++; } while(++p != m.end()); cout << "Read " << IceUtil::Time::milliSeconds(oldMs).toDateTime() << " in all records;" << " updating with " << time.toDateTime() << " ... " << flush; txHolder.commit(); cout << "done" << endl; test(count == size); } connection->close(); communicator->destroy(); return EXIT_SUCCESS; }