Ejemplo C++ (múltiples conexiones simultáneas)

En C++, hay dos formas de manejar múltiples conexiones simultáneas de forma independiente. La primera es creando un hilo para cada uno utilizando pthreads. La segunda es mediante la bifurcación de un nuevo proceso para manejar la conexión, que es el método demostrado en este ejemplo. Este ejemplo se basa en el ejemplo de la formadora y la clasificadora, pero con cambios en la principal.

En este ejemplo, getApi se llama con un TRUE para indicar el modo de bifurcación, obteniendo de vuelta un puntero en lugar de una referencia. En modo remoto hay dos procesos. El proceso padre recibe un NULL de vuelta, incrementa el contador hijo y no hace nada; hace esto dos veces. En el proceso hijo después de la bifurcación, getApi devuelve la API con la que manejar un shaper o sizer y luego sale.

Este ejemplo utiliza el siguiente nombre de archivo:
fork.cpp

Código

#include <nzaefactory.hpp>

using namespace nz::ae;

static int run(nz::ae::NzaeFunction *aeFunc);
static int doShaper(nz::ae::NzaeShaper *aeShaper);

int main(int argc, char * argv[])
{
    NzaeApiGenerator helper;
    // The following line is only needed if a launcher is not used
    helper.setName("testcapi");
    int i = 0;
    int j=0;
    while (i < 1) {
        nz::ae::NzaeApi *api = helper.getApi(nz::ae::NzaeApi::ANY, true);
        if (helper.isRemote() && !api) {
            // fork mode (parent)
            j++;
            if (j == 2)
                break;
            continue;
        }
        if (api->apiType == nz::ae::NzaeApi::FUNCTION) {
            run(api->aeFunction);
            i++;
        }
        else {
            doShaper(api->aeShaper);
        }
        if (!helper.isRemote())
            break;
        if (api)
            break;
    }

    return 0;
}

class MyHandler : public nz::ae::NzaeFunctionMessageHandler
{
public:
    void evaluate(NzaeFunction& api, NzaeRecord &input, NzaeRecord &result) {
        const NzaeMetadata& m = api.getMetadata();
        nz::ae::NzaeField &field = input.get(0);
        if (!field.isNull() ) {
            nz::ae::NzaeField &f = result.get(0);
            if (field.type() == NzaeDataTypes::NZUDSUDX_NUMERIC32 ||
                field.type() == NzaeDataTypes::NZUDSUDX_NUMERIC64 ||
                field.type() == NzaeDataTypes::NZUDSUDX_NUMERIC128)
            {
                NzaeNumericField &nf = (NzaeNumericField&)field;
                if (m.getInputSize(0) != nf.precision() ||
                    m.getInputScale(0) != nf.scale()) {
                    NzaeNumeric128Field* np = nf.toNumeric128(38, 5);
                    f.assign(*np);
                    delete np;
                }
                else
                    f.assign(field);
            }
            else {
                f.assign(field);
            }
        }
    } 
};

class MyHandler2 : public nz::ae::NzaeShaperMessageHandler
{
public:
    void shaper(NzaeShaper& api){
        const NzaeMetadata& m = api.getMetadata();
        char name[2];
        if (api.catalogIsUpper())
            name[0] = 'I';
        else
            name[0] = 'i';
        name[1] = 0;

        if (m.getInputType(0) == NzaeDataTypes::NZUDSUDX_FIXED ||
            m.getInputType(0) == NzaeDataTypes::NZUDSUDX_VARIABLE ||
            m.getInputType(0) == NzaeDataTypes::NZUDSUDX_NATIONAL_FIXED ||
            m.getInputType(0) == NzaeDataTypes::NZUDSUDX_NATIONAL_VARIABLE) {
            api.addOutputColumnString(m.getInputType(0), name,
m.getInputSize(0));
        }
        else if (m.getInputType(0) == NzaeDataTypes::NZUDSUDX_NUMERIC128 ||
                m.getInputType(0) == NzaeDataTypes::NZUDSUDX_NUMERIC64 ||
                m.getInputType(0) == NzaeDataTypes::NZUDSUDX_NUMERIC32) {
            api.addOutputColumnNumeric(m.getInputType(0), name,
m.getInputSize(0),
                                             m.getInputScale(0));
        }
        else {
            api.addOutputColumn(m.getInputType(0), name);
        }
    }
};

static int doShaper(nz::ae::NzaeShaper *aeShaper)
{
    aeShaper->run(new MyHandler2());
    return 0;
}

static int run(nz::ae::NzaeFunction *aeFunc)
{
    aeFunc->run(new MyHandler());
    return 0;
}

Una compilación

Compila como sigue:

$NZ_EXPORT_DIR/ae/utilities/bin/compile_ae --language cpp --template compile \
     --exe forkae --compargs "-g -Wall" --linkargs "-g" fork.cpp --version 3

Registro

Para el registro, utilice una variación remota para demostrar el modo de horquilla que sólo funciona en modo remoto:

$NZ_EXPORT_DIR/ae/utilities/bin/register_ae --sig "rem_forkae(VARARGS)" \
     --return "table(ANY)" --language cpp --template udtf --exe forkae \
     --version 3 --remote --rname testcapi

$NZ_EXPORT_DIR/ae/utilities/bin/register_ae --sig "rem_fork_launch(int8)" \
     --return "TABLE(aeresult varchar(255))" --language cpp --template udtf \
     --exe forkae --version 3 --remote --launch --rname testcapi

En ejecución

A correr:

SELECT * FROM TABLE WITH FINAL(rem_fork_launch(0));
                                 AERESULT
------------------------------------------------------------------------
 tran: 7522 DATA slc: 0 hardware: 0 machine: spubox1 process: 3800 thread: 3800
(1 row)
SELECT * FROM TABLE WITH FINAL(rem_fork_launch(0));
                              AERESULT
------------------------------------------------------------------------
tran: 7606 DATA slc: 0 hardware: 0 machine: spubox1 process: 6560 thread: 6560
(1 row)

SELECT * FROM TABLE WITH FINAL(rem_forkae('test'));
 I
------
 test
(1 row)