Vectors.cpp

// Vectors.cpp
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2017

@import "PythonUtilityFunctions.h"
@import "Ceda/cxPython/cxPython.h"
@import "Ceda/cxWorkingSetIpc/WorkingSetIPC.h"
@import "Ceda/cxOperation/IWorkingSetMachine.h"
@import "Ceda/cxPersistStore/IPersistStore.h"
@import "Ceda/cxPersistStore/pref.h"
@import "Ceda/cxObject/Object.h"
@import "Ceda/cxObject/IObjectVisitor.h"
@import "Ceda/cxObject/WCSpace.h"
@import "Ceda/cxObject/PrintReflectedVariable.h"
#include "Ceda/cxUtils/TracerUtils.h"

namespace VectorOfInt64InModel
{
    $model+ Point // << passbyvalue returnbyvalue >>
    {
        float64 X;
        float64 Y;
    };
    
    $struct+ X isa ceda::IPersistable :
        model
        {
            xvector<int64> S;
            xvector<Point> P;
        }
    {
    };

    $function+ X* AsX(ceda::ptr<ceda::IObject> obj)
    {
        return ceda::tryqccast<X>(obj);
    }

    void Run()
    {
        ceda::TraceGroup g("xvector<int64> in model example");

        PyRun_SimpleString(
            @strx(mPythonUtilityFunctions)
            "\n"
            @strx
            (
                import random
                ns = rootnamespace.VectorOfInt64InModel
                Point = ns.Point
                X = ns.X

                def chooseRandomValue():
                    return random.randint(0,20)

                def chooseRandomValueInList(L):
                    return L[random.randint(0,len(L)-1)] if L else None

                def chooseRandomList():
                    L = []
                    n = random.randint(0,3)
                    for i in range(n):
                        L.append(chooseRandomValue())
                    return L

                def createRootObjectInDatabase():
                    return X.new()

                def printRootObjectInDatabase(r):
                    print `r`

                def printInfoAboutS(S):
                    print 'S = ' + `S`
                    print 'bool(S) = ' + `bool(S)`
                    print 'str(S) = ' + `str(S)`
                    print 'repr(S) = ' + `repr(S)`
                    print 'len(S) = ' + `len(S)`
                    if S:
                        print 'min(S) = ' + `min(S)`
                        print 'max(S) = ' + `max(S)`
                    print 'S.index(2) = ' + `S.index(2)`
                    print 'S.index(9) = ' + `S.index(9)`
                    print 'S.index(15) = ' + `S.index(15)`
                    print 'S.count(4) = ' + `S.count(4)`
                    print 'S.count(20) = ' + `S.count(20)`
                    print 'S*2 = ' + `S*2`
                    if S:
                        print 'S[-1] = ' + `S[-1]`
                    print '3 in S = ' + `3 in S`
                    print '10 in S = ' + `10 in S`
                    print '3 not in S = ' + `3 not in S`
                    print '10 not in S = ' + `10 not in S`
                    print 'S+[100,200] = ' + `S+[100,200]`
                    if len(S) > 2:
                        print 'S[1] = ' + `S[1]`
                        print 'S[1:3] = ' + `S[1:3]`

                dbServerPath = 'server_database'
                dbClientPath = 'client_database'
                utRootKey = 'mykey'
                
                dbServer = Database()
                dbServer.open(dbServerPath, createNew=True, dataSetMaster=True)
                dbServer.createServer(3000)

                dbClient = Database()
                dbClient.open(dbClientPath, createNew=True, dataSetMaster=False)
                dbClient.createClient("127.0.0.1", 3000)

                rootObject = dbServer.bootstrapRootObject(utRootKey, createRootObjectInDatabase)
                with Txn(dbServer):
                    printRootObjectInDatabase(rootObject)

                with Txn(dbServer):
                    P = rootObject.P
                    P.append( Point(1,2) )
                    P.append( Point(3,4) )
                    P.append( Point(5,6) )

                time.sleep(0.1)

                with Txn(dbServer):
                    del P[0:1]

                # Reports error: cannot assign attribute X of read-only VectorOfInt64InModel::Point
                # This assignment is bad and leads to divergence because it is not recorded as an operation on the working set.
                # cxPython doesnt allow giving mutative access to elements of vectors in models.
                #with Txn(dbServer):
                #    P[0].X = 10

                with Txn(dbServer):
                    S = rootObject.S
                    for i in range(100):
                        s = len(S)
                        n = random.randint(0,7)
                        if n == 0:
                            v = chooseRandomValue()
                            print 'S.append(' + `v` + ')'
                            S.append(v)
                        elif n == 1:
                            p = random.randint(0,s)
                            v = chooseRandomValue()
                            print 'S.insert(' + `p` + ',' + `v` + ')'
                            S.insert(p,v)
                        elif n == 2 and S:
                            print 'S.pop()'
                            S.pop()
                        elif n == 3:
                            i1 = random.randint(0,s)
                            i2 = random.randint(i1,s)
                            print 'del S[' + `i1` + ':' + `i2` + ']'
                            del S[i1:i2]
                        elif n == 4 and S:
                            v = chooseRandomValueInList(S)
                            print 'S.remove(' + `v` + ')'
                            S.remove(v)
                        elif n == 5 and S:
                            p = random.randint(0,s-1)
                            v = chooseRandomValue()
                            print 'S[' + `p` + '] = ' + `v`
                            S[p] = v
                        elif n == 6:
                            i1 = random.randint(0,s)
                            i2 = random.randint(i1,s)
                            L = chooseRandomList()
                            print 'S[' + `i1` + ':' + `i2` + '] = ' + `L`
                            S[i1:i2] = L
                        elif n == 7:
                            L = chooseRandomList()
                            print 'S.extend(' + `L` + ')'
                            S.extend(L)
                        print '    ' + `S`

                    printRootObjectInDatabase(rootObject)

                with Txn(dbServer):
                    printInfoAboutS(rootObject.S)

                # Sleep for 0.1 seconds, which is long enough to replicate the data
                time.sleep(0.1)

                with Txn(dbClient):
                    entryPoint = dbClient.utRoot.Map[utRootKey]
                    if entryPoint:
                        clientRootObject = entryPoint[0].self
                        print 'Client:'
                        printRootObjectInDatabase(clientRootObject)

                dbClient.close()
                dbServer.close()
            ));
    }
}

namespace Vectors
{
    void Run()
    {
        for (int i=0 ; i < 1 ; ++i)
        {
            VectorOfInt64InModel::Run();
        }
    }
}