Ejemplo n.º 1
0
int
Test::ServantI::getTotalBalance(const Current& current)
{
    Test::AccountPrxSeq proxies = getAccounts(current);

    //
    // Need to start a transaction to ensure a consistent result
    //
    Freeze::TransactionalEvictorPtr te = Freeze::TransactionalEvictorPtr::dynamicCast(_evictor);

    for(;;)
    {
        test(te->getCurrentTransaction() == 0);
        Freeze::ConnectionPtr con = Freeze::createConnection(current.adapter->getCommunicator(), _remoteEvictor->envName());
        te->setCurrentTransaction(con->beginTransaction());
        int total = 0;
        try
        {
            for(size_t i = 0; i < proxies.size(); ++i)
            {
                total += proxies[i]->getBalance();
            }
            te->getCurrentTransaction()->rollback();
            te->setCurrentTransaction(0);
            return total;
        }
        catch(const Freeze::TransactionalEvictorDeadlockException&)
        {
            te->getCurrentTransaction()->rollback();
            te->setCurrentTransaction(0);
            // retry
        }
        catch(...)
        {
            te->getCurrentTransaction()->rollback();
            te->setCurrentTransaction(0);
            throw;
        }
    }
    return -1;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
        // reload existing bets into the bet resolver
        //

        _bankPrx->reloadBets();

        //
        // Create players / recreate missing players missing players using a transaction
        // (the transaction is not really necessary here, but a good demo)
        //

        const string players[] =
        {
            "al", "bob", "charlie", "dave", "ed", "fred", "gene", "herb", "irvin", "joe", "ken", "lance"
        };

        Freeze::ConnectionPtr connection = Freeze::createConnection(communicator(), _envName);
        Freeze::TransactionPtr tx = connection->beginTransaction();

        _playerEvictor->setCurrentTransaction(tx);

        for(size_t i = 0; i < 12; ++i)
        {
            Ice::Identity ident = { players[i], "player" };
            if(!_playerEvictor->hasObject(ident))
            {
                _playerEvictor->add(new PlayerI, ident);
            }
        }

        tx->commit();
        assert(_playerEvictor->getCurrentTransaction() == 0);
Ejemplo n.º 4
0
int
WarehouseServer::run(int argc, char* argv[])
{
    bool useSimpleEvictor = argc > 1 && string(argv[1]) == "simple";

    if(useSimpleEvictor)
    {
        cout << "Using SimpleEvictor" << endl;
    }
    else
    {
        cout << "Using Evictor implemented with IceUtil::Cache" << endl; 
    }

    Ice::ObjectAdapterPtr adapter = communicator()->createObjectAdapter("Warehouse");

    const string envName = "db";
    const string dbName = "items";

    {
        //
        // Open our database, a Freeze dictionary.
        //
        Freeze::ConnectionPtr connection = Freeze::createConnection(communicator(), envName);
        Database db(connection, dbName);

        if(db.empty())
        {
            cout << "Creating new database..." << flush;

            //
            // Populate database with objectCount entries.
            //
            ItemInfo info;

            connection->beginTransaction();

            for(int i = 0; i < objectCount; ++i)
            {
                ostringstream os;
                os << "P/N " << i;
                string name = os.str();
                info.description = "The description of " + name;
                info.unitPrice = i + 0.95f;
                info.quantityInStock = i;
                info.filler = string(5000, 'x');

                db.put(Database::value_type(name, info));
            }
            connection->currentTransaction()->commit();
            cout << "done" << endl;
        }
    }

    CurrentDatabase currentDb(communicator(), envName, dbName);

    //
    // This servant locator (evictor) will intercept all categories.
    //
    if(useSimpleEvictor)
    {
        adapter->addServantLocator(new SimpleEvictor(currentDb, evictorSize), "");
    }
    else
    {
        adapter->addServantLocator(new Evictor(currentDb, evictorSize), "");
    }

    adapter->activate();
    communicator()->waitForShutdown();
    return EXIT_SUCCESS;
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
/*static*/ void
Freeze::MapHelper::recreate(const Freeze::ConnectionPtr& connection,
                            const string& dbName,
                            const string& key,
                            const string& value,
                            const Freeze::KeyCompareBasePtr& keyCompare,
                            const std::vector<MapIndexBasePtr>& indices)
{
    Freeze::ConnectionIPtr connectionI = Freeze::ConnectionIPtr::dynamicCast(connection.get());
    if(connectionI == 0)
    {
        throw DatabaseException(__FILE__, __LINE__, "Invalid connection");
    }

    if(dbName == catalogName() || dbName == catalogIndexListName())
    {
        throw DatabaseException(__FILE__, __LINE__,
                                "You cannot destroy recreate the \"" + dbName + "\" database");
    }

    if(connectionI->trace() >= 1)
    {
        Trace out(connectionI->communicator()->getLogger(), "Freeze.Map");
        out << "Recreating \"" << dbName << "\"";
    }

    TransactionPtr tx = connectionI->currentTransaction();
    bool ownTx = (tx == 0);

    Dbt keyDbt;
    keyDbt.set_flags(DB_DBT_REALLOC);
    Dbt valueDbt;
    valueDbt.set_flags(DB_DBT_REALLOC);

    try
    {
        for(;;)
        {
            try
            {
                if(ownTx)
                {
                    tx = 0;
                    tx = connectionI->beginTransaction();
                }

                DbTxn* txn = connectionI->dbTxn();

                if(connectionI->trace() >= 2)
                {
                    Trace out(connectionI->communicator()->getLogger(), "Freeze.Map");
                    out << "Removing all existing indices for \"" << dbName << "\"";
                }
                CatalogIndexList catalogIndexList(connection, catalogIndexListName());
                CatalogIndexList::iterator p = catalogIndexList.find(dbName);
                if(p != catalogIndexList.end())
                {
                    const StringSeq& idxs = p->second;

                    for(size_t i = 0; i < idxs.size(); ++i)
                    {
                        try
                        {
                            connection->removeMapIndex(dbName, idxs[i]);
                        }
                        catch(const IndexNotFoundException&)
                        {
                            //
                            // Ignored
                            //
                        }
                    }
                    catalogIndexList.erase(p);
                }

                //
                // Rename existing database
                //
                string oldDbName = dbName + ".old-" + generateUUID();

                if(connectionI->trace() >= 2)
                {
                    Trace out(connectionI->communicator()->getLogger(), "Freeze.Map");
                    out << "Renaming \"" << dbName << "\" to \"" << oldDbName << "\"";
                }

                connectionI->dbEnv()->getEnv()->dbrename(txn, dbName.c_str(), 0, oldDbName.c_str(), 0);

                //
                // Fortunately, DB closes oldDb automatically when it goes out of scope
                //
                Db oldDb(connectionI->dbEnv()->getEnv(), 0);

                //
                // Berkeley DB expects file paths to be UTF8 encoded.
                //
                oldDb.open(txn, nativeToUTF8(oldDbName, getProcessStringConverter()).c_str(),
                           0, DB_BTREE, DB_THREAD, FREEZE_DB_MODE);

                IceInternal::UniquePtr<MapDb> newDb(new MapDb(connectionI, dbName, key, value, keyCompare, indices, true));

                if(connectionI->trace() >= 2)
                {
                    Trace out(connectionI->communicator()->getLogger(), "Freeze.Map");
                    out << "Writing contents of \"" << oldDbName << "\" to fresh \"" << dbName << "\"";
                }

                //
                // Now simply write all of oldDb into newDb
                //
                Dbc* dbc = 0;
                oldDb.cursor(txn, &dbc, 0);

                try
                {
                    while(dbc->get(&keyDbt, &valueDbt, DB_NEXT) == 0)
                    {
                        newDb->put(txn, &keyDbt, &valueDbt, 0);
                    }
                }
                catch(...)
                {
                    dbc->close();
                    throw;
                }
                dbc->close();

                if(connectionI->trace() >= 2)
                {
                    Trace out(connectionI->communicator()->getLogger(), "Freeze.Map");
                    out << "Transfer complete; removing \"" << oldDbName << "\"";
                }
                connectionI->dbEnv()->getEnv()->dbremove(txn, oldDbName.c_str(), 0, 0);

                if(ownTx)
                {
                    tx->commit();
                }

                break; // for (;;)
            }
            catch(const DbDeadlockException& dx)
            {
                if(ownTx)
                {
                    if(connectionI->deadlockWarning())
                    {
                        Warning out(connectionI->communicator()->getLogger());
                        out << "Deadlock in Freeze::MapHelperI::recreate on Db \""
                            << dbName << "\"; retrying ...";
                    }

                    //
                    // Ignored, try again
                    //
                }
                else
                {
                    throw DeadlockException(__FILE__, __LINE__, dx.what(), tx);
                }
            }
            catch(const DbException& dx)
            {
                if(ownTx)
                {
                    try
                    {
                        tx->rollback();
                    }
                    catch(...)
                    {
                    }
                }

                throw DatabaseException(__FILE__, __LINE__, dx.what());
            }
            catch(...)
            {
                if(ownTx && tx != 0)
                {
                    try
                    {
                        tx->rollback();
                    }
                    catch(...)
                    {
                    }
                }
                throw;
            }
        }
        free(keyDbt.get_data());
        free(valueDbt.get_data());
    }
    catch(...)
    {
        free(keyDbt.get_data());
        free(valueDbt.get_data());

        throw;
    }
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
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;
}