Example #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;
}
Example #2
0
int
run(int, char**, const Ice::CommunicatorPtr& communicator, bool transactional, bool shutdown)
{
    string ref = "factory:default -p 12010";
    Ice::ObjectPrx base = communicator->stringToProxy(ref);
    test(base);
    Test::RemoteEvictorFactoryPrx factory = Test::RemoteEvictorFactoryPrx::checkedCast(base);

    if(transactional)
    {
        cout << "testing transactional Freeze Evictor... " << flush;
    }
    else
    {
        cout << "testing background-save Freeze Evictor... " << flush;
    }
    
    const Ice::Int size = 5;
    Ice::Int i;
    
    Test::RemoteEvictorPrx evictor = factory->createEvictor("Test", transactional);
    
    evictor->setSize(size);
    
    //
    // Create some servants 
    //
    vector<Test::ServantPrx> servants;
    for(i = 0; i < size; i++)
    {
        ostringstream ostr;
        ostr << i;
        string id = ostr.str();
        servants.push_back(evictor->createServant(id, i));
        servants[i]->ice_ping();
        
        Test::FacetPrx facet1 = Test::FacetPrx::uncheckedCast(servants[i], "facet1");
        try
        {
            facet1->ice_ping();
            test(false);
        }
        catch(const Ice::FacetNotExistException&)
        {
            // Expected
        }

        servants[i]->addFacet("facet1", "data");
        facet1->ice_ping();
        facet1 = Test::FacetPrx::checkedCast(servants[i], "facet1");
        test(facet1);
        facet1->setValue(10 * i);
        facet1->addFacet("facet2", "moreData");
        Test::FacetPrx facet2 = Test::FacetPrx::checkedCast(facet1, "facet2");
        test(facet2);
        facet2->setValue(100 * i);
    }
   
    //
    // Evict and verify values.
    //
    evictor->setSize(0);
    evictor->setSize(size);
    for(i = 0; i < size; i++)
    {
        test(servants[i]->getValue() == i);
        Test::FacetPrx facet1 = Test::FacetPrx::checkedCast(servants[i], "facet1");
        test(facet1);
        test(facet1->getValue() == 10 * i);
        test(facet1->getData() == "data");
        Test::FacetPrx facet2 = Test::FacetPrx::checkedCast(facet1, "facet2");
        test(facet2);
        test(facet2->getData() == "moreData");
    }
    
    //
    // Mutate servants.
    //
    for(i = 0; i < size; i++)
    {
        servants[i]->setValue(i + 100);
        Test::FacetPrx facet1 = Test::FacetPrx::checkedCast(servants[i], "facet1");
        test(facet1);
        facet1->setValue(10 * i + 100);
        Test::FacetPrx facet2 = Test::FacetPrx::checkedCast(facet1, "facet2");
        test(facet2);
        facet2->setValue(100 * i + 100);
    }
    
    //
    // Evict and verify values.
    //
    evictor->setSize(0);
    evictor->setSize(size);
    for(i = 0; i < size; i++)
    {
        test(servants[i]->getValue() == i + 100);
        Test::FacetPrx facet1 = Test::FacetPrx::checkedCast(servants[i], "facet1");
        test(facet1);
        test(facet1->getValue() == 10 * i + 100);
        Test::FacetPrx facet2 = Test::FacetPrx::checkedCast(facet1, "facet2");
        test(facet2);
        test(facet2->getValue() == 100 * i + 100);
    }

    if(!transactional)
    {
        // 
        // Test saving while busy
        //
        for(i = 0; i < size; i++)
        {
            //
            // Start a mutating operation so that the object is not idle.
            //
            servants[i]->begin_setValueAsync(i + 300);
            
            test(servants[i]->getValue() == i + 100);
            //
            // This operation modifies the object state but is not saved
            // because the setValueAsync operation is still pending.
            //
            servants[i]->setValue(i + 200);
            test(servants[i]->getValue() == i + 200);
            
            //
            // Force the response to setValueAsync
            //
            servants[i]->releaseAsync();
            test(servants[i]->getValue() == i + 300);
        }
    }

    //
    // Add duplicate facet and catch corresponding exception
    // 
    for(i = 0; i < size; i++)
    {
        try
        {
            servants[i]->addFacet("facet1", "foobar");
            test(false);
        }
        catch(const Test::AlreadyRegisteredException&)
        {
        }
    }
    
    //
    // Remove a facet that does not exist
    // 
    try
    {
        servants[0]->removeFacet("facet3");
        test(false);
    }
    catch(const Test::NotRegisteredException&)
    {
    }

    //
    // Call an operation that does not exist on the servant
    //    
    try
    {
        Test::AccountPrx::uncheckedCast(servants[0])->getBalance();
        test(false);
    }
    catch(const Ice::OperationNotExistException&)
    {
    }
  
    //
    // Remove all facets
    //
    for(i = 0; i < size; i++)
    {
        servants[i]->removeFacet("facet1");
        servants[i]->removeFacet("facet2");
    }

    //
    // Check they are all gone
    //
    for(i = 0; i < size; i++)
    {
        Test::FacetPrx facet1 = Test::FacetPrx::checkedCast(servants[i], "facet1");
        test(facet1 == 0);
        Test::FacetPrx facet2 = Test::FacetPrx::checkedCast(servants[i], "facet2");
        test(facet2 == 0);
    }

    evictor->setSize(0);
    evictor->setSize(size);

    //
    // Destroy servants and verify ObjectNotExistException.
    //
    for(i = 0; i < size; i++)
    {
        servants[i]->destroy();
        try
        {
            servants[i]->getValue();
            test(false);
        }
        catch(const Ice::ObjectNotExistException&)
        {
            // Expected
        }

        try
        {
            servants[i]->ice_ping();
            test(false);
        }
        catch(const Ice::ObjectNotExistException&)
        {
            // Expected
        }
    }
          
    //
    // Recreate servants, set transient value
    //  
    servants.clear();
    for(i = 0; i < size; i++)
    {
        ostringstream ostr;
        ostr << i;
        string id = ostr.str();
        servants.push_back(evictor->createServant(id, i));
        servants[i]->setTransientValue(i);
    }
    
    //
    // Evict all
    //
    evictor->saveNow();
    evictor->setSize(0);
    evictor->setSize(size);
    
    //
    // Check the transient value
    //
    for(i = 0; i < size; i++)
    {
        test(servants[i]->getTransientValue() == -1);
    }

    if(!transactional)
    {
    
        //
        // Now with keep
        //
        for(i = 0; i < size; i++)
        {
            servants[i]->keepInCache();
            servants[i]->keepInCache();
            servants[i]->setTransientValue(i);
        }
        evictor->saveNow();
        evictor->setSize(0);
        evictor->setSize(size);
   
    
        //
        // Check the transient value
        //
        for(i = 0; i < size; i++)
        {
            test(servants[i]->getTransientValue() == i);
        }

        //
        // Again, after one release
        //
        for(i = 0; i < size; i++)
        {
            servants[i]->release();
        }
        evictor->saveNow();
        evictor->setSize(0);
        evictor->setSize(size);
        for(i = 0; i < size; i++)
        {
            test(servants[i]->getTransientValue() == i);
        }

        //
        // Again, after a second release
        //
        for(i = 0; i < size; i++)
        {
            servants[i]->release();
        }
        evictor->saveNow();
        evictor->setSize(0);
        evictor->setSize(size);
        for(i = 0; i < size; i++)
        {
            test(servants[i]->getTransientValue() == -1);
        }


        //
        // Release one more time
        //
        for(i = 0; i < size; i++)
        {
            try
            {
                servants[i]->release();
                test(false);
            }
            catch(const Test::NotRegisteredException&)
            {
                // Expected
            }
        }
    }

    if(transactional)
    {
        int totalBalance = servants[0]->getTotalBalance();
        test(totalBalance == 0);
        
        Test::AccountPrxSeq accounts = servants[0]->getAccounts();
        test(accounts.size() > 0);

        totalBalance = servants[0]->getTotalBalance();
        test(totalBalance > 0);

        const int threadCount = static_cast<int>(accounts.size());
        
        vector<ThreadPtr> threads(threadCount);
        for(i = 0; i < threadCount; i++)
        {
            threads[i] = new TransferThread(accounts);
            threads[i]->start();
        }

        for(i = 0; i < threadCount; i++)
        {
            threads[i]->getThreadControl().join();
        }
       
        //
        // Check that the total balance did not change!
        //
        test(totalBalance == servants[0]->getTotalBalance());
    }
        
    //
    // Deactivate and recreate evictor, to ensure that servants
    // are restored properly after database close and reopen.
    //
    evictor->deactivate();
    
    evictor = factory->createEvictor("Test", transactional);

    evictor->setSize(size);
    for(i = 0; i < size; i++)
    {
        ostringstream ostr;
        ostr << i;
        string id = ostr.str();

        servants[i] = evictor->getServant(id);
        test(servants[i]->getValue() == i);
    }

    //
    // Test concurrent lookups with a smaller evictor
    // size and one missing servant
    //
    evictor->setSize(size / 2);
    servants[0]->destroy();

    {
        const int threadCount = size * 2;
        
        ThreadPtr threads[threadCount];
        for(i = 0; i < threadCount; i++)
        {
            threads[i] = new ReadThread(servants);
            threads[i]->start();
        }
        
        for(i = 0; i < threadCount; i++)
        {
            threads[i]->getThreadControl().join();
        }
    }
    
    //
    // Clean up.
    //
    evictor->destroyAllServants("");
    evictor->destroyAllServants("facet1");
    evictor->destroyAllServants("facet2");

    //
    // CreateDestroy threads
    //
    {
        const int threadCount = size;;
        
        ThreadPtr threads[threadCount];
        for(i = 0; i < threadCount; i++)
        {
            threads[i] = new CreateDestroyThread(evictor, i, size);
            threads[i]->start();
        }
        
        for(i = 0; i < threadCount; i++)
        {
            threads[i]->getThreadControl().join();
        }

        //
        // Verify all destroyed
        // 
        for(i = 0; i < size; i++)   
        {
            try
            {
                servants[i]->getValue();
                test(false);
            }
            catch(const Ice::ObjectNotExistException&)
            {
                // Expected
            }
        }
    }

    //
    // Recreate servants.
    //  
    servants.clear();
    for(i = 0; i < size; i++)
    {
        ostringstream ostr;
        ostr << i;
        string id = ostr.str();
        servants.push_back(evictor->createServant(id, i));
    }

    //
    // Deactivate in the middle of remote AMD operations
    // (really testing Ice here)
    //
    {
        const int threadCount = size;
        
        ReadForeverThreadPtr threads[threadCount];
        for(i = 0; i < threadCount; i++)
        {
            threads[i] = new ReadForeverThread(servants);
            threads[i]->start();
        }

        ThreadControl::sleep(Time::milliSeconds(500));
        for(i = 0; i < threadCount; i++)
        {
            threads[i]->setState(ReadForeverThread::StateDeactivating);
        }
        evictor->deactivate();
        for(i = 0; i < threadCount; i++)
        {
            threads[i]->setState(ReadForeverThread::StateDeactivated);
        }

        for(i = 0; i < threadCount; i++)
        {
            threads[i]->getThreadControl().join();
        }
    }

    //
    // Resurrect
    //
    evictor = factory->createEvictor("Test", transactional);
    evictor->destroyAllServants("");

    //
    // Deactivate in the middle of adds
    //
    {
        const int threadCount = size;
        
        AddForeverThreadPtr threads[threadCount];
        for(i = 0; i < threadCount; i++)
        {
            threads[i] = new AddForeverThread(evictor, i);
            threads[i]->start();
        }

        ThreadControl::sleep(Time::milliSeconds(500));
        for(i = 0; i < threadCount; i++)
        {
            threads[i]->setState(AddForeverThread::StateDeactivating);
        }
        evictor->deactivate();
        for(i = 0; i < threadCount; i++)
        {
            threads[i]->setState(AddForeverThread::StateDeactivated);
        }
        
        for(i = 0; i < threadCount; i++)
        {
            threads[i]->getThreadControl().join();
        }
    }
    
    
    //
    // Clean up.
    //
    evictor = factory->createEvictor("Test", transactional);
    evictor->destroyAllServants("");
    evictor->deactivate();

    cout << "ok" << endl;

    if(shutdown)
    {
        factory->shutdown();
    }
    
    return EXIT_SUCCESS;
}