MultiPSpaceTxn.cpp

// MultiPSpaceTxn.cpp
//
// Author Jesse Pepper, David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2007

@import "Ceda/cxPersistStore/IPersistStore.h"
@import "Ceda/cxObject/CSpace.h"
#include "Ceda/cxUtils/FileException.h"
#include "Ceda/cxUtils/Environ.h"
#include "Ceda/cxUtils/TracerUtils.h"
#include "Ceda/cxUtils/AutoCloser.h"
#include <assert.h>

namespace MultiPSpaceTxn
{
    // This example demonstrates a mutative (exclusive locked) transaction across two PSpaces.

    $interface+ IBankAccount : ceda::IPersistable
    {
        void Deposit(ceda::float64 value);
        void Withdraw(ceda::float64 value);
        ceda::float64 GetBalance() const;
    };
    
    $struct BankAccount isa IBankAccount :
        model
        {
            ceda::float64 m_balance;
        }
    {
        // (DBL) todo. Initialisation of data model members needs to be looked at carefully.
        // The code below generates an operation!
        BankAccount() { m_balance = 0.0; }  
        
        void Deposit(ceda::float64 value) { m_balance = m_balance + value; }
        void Withdraw(ceda::float64 value) { m_balance = m_balance - value; }
        ceda::float64 GetBalance() const { return m_balance; }
    };
    
    void Run()
    {
        ceda::TraceGroup g("Multi-PSpace Transaction Example");

        // todo : currently this example produces an assertion in DGSystem::DataSourceReadBarrier()
        // This is because a read barrier is invoked on an object that belongs in a different CSpace.
        return;
        
        // Create store
        ceda::xstring path = ceda::GetCedaTestPath("MultiSpaceTest.ced");
        ceda::close_ptr<ceda::PersistStore> pstore(ceda::OpenPersistStore(path.c_str(), ceda::OM_CREATE_ALWAYS));

        // Create pspaces and bootstrap BankAccount roots
        ceda::WPSpace p1(ceda::OpenPSpace(pstore.get(), "ps1"));
        ceda::ptr<IBankAccount> a1 = ceda::BootstrapPSpaceRoot<BankAccount>("my_root");

        ceda::WPSpace p2(ceda::OpenPSpace(pstore.get(), "ps2"));
        ceda::ptr<IBankAccount> a2 = ceda::BootstrapPSpaceRoot<BankAccount>("my_root");
        
        // An array of PSpaceLockMode structures specifies which PSpaces are to be locked and
        // what type of lock to achieve for each.
        //ceda::PSpaceLockMode lms[2] =
        //{
        //    { p1, ceda::ECSpaceLockMode::Exclusive },
        //    { p2, ceda::ECSpaceLockMode::Exclusive },
        //};
       
        ceda::CSpace* spaces[2] = 
        {
            GetCSpace(p1), 
            GetCSpace(p2)
        };
        ceda::LockMultipleCSpaces(spaces,2,ceda::ECSpaceLockMode::Exclusive);
        
        {
            //ceda::close_ptr<ceda::PersistStoreTxn> txn(OpenTxn(pstore.get(),lms,2));
            
            ceda::float64 value = 85.0;
            a2->Withdraw(value);
            a1->Deposit(value);
            
            Tracer() << "After transaction, a1.balance = " << a1->GetBalance() << ", a2.balance = " << a2->GetBalance() << '\n';
        }
        
        ceda::UnlockMultipleCSpaces(spaces, 2);
    }
}