C++ language logging and runtime information

This example uses the following file name: runtime.cpp

Code

The code in this example explores functionality that may not be commonly used. Logging can be used to help trace the execution of an AE. To be of use, the AE must be registered with a log mask and logging must be enabled via nzudxdbg. To receive system logging messages in the window where the NPS system was started, you need to start NPS with the '-i' option (for example, 'nzstart -i'). This causes the NPS processes to remain attached to the terminal. Runtime information provides statistics about the NPS system, including the number of dataslices, the number of SPUs, and locus of execution.

#include <nzaefactory.hpp>
using namespace nz::ae;
static int run(nz::ae::NzaeFunction *aeFunc);

int main(int argc, char * argv[])
{
    NzaeApiGenerator helper;
    // The following line is only needed if a launcher is not used
    helper.setName("testcapi");
    for (int i=0; i < 2; i++) {
        nz::ae::NzaeApi &api = helper.getApi(nz::ae::NzaeApi::FUNCTION);
        run(api.aeFunction);
        if (!helper.isRemote())
            break;
    }
    return 0;
}

static void validateRuntime(NzaeFunction *aeFunc, int64_t *args, int type)
{
    // argss:
    // dataslice, transaction, hardware, numslices, numspus, locus
    int64_t dataslice = args[0];
    int64_t txid = args[1];
    int64_t hwid = args[2];
    int64_t nslices = args[3];
    int64_t nspus = args[4];
    int64_t locus = args[5];
    const NzaeRuntime &aeRun = aeFunc->getRuntime();
    char buf[1024];

    if (locus != (int64_t)aeRun.getLocus())
    {
        sprintf(buf, "test fails: 1\n");
        aeFunc->log(NzaeFunction::LOG_DEBUG, buf);
    }
    if (aeRun.getSuggestedMemoryLimit() != 123)
    {
        sprintf(buf, "test fails: 7 \n");
        aeFunc->log(NzaeFunction::LOG_DEBUG, buf);
    }
    if (aeRun.getUserQuery() == false)
    {
        sprintf(buf, "test fails: 8 \n");
        aeFunc->log(NzaeFunction::LOG_DEBUG, buf);
    }
    if (type != (int64_t)aeRun.getAdapterType())
    {
        sprintf(buf, "test fails: 9 \n");
        aeFunc->log(NzaeFunction::LOG_DEBUG, buf);
    }
        if (locus == (int64_t)NzaeRuntime::NZAE_LOCUS_POSTGRES) {
        return;
    }

    if (dataslice != (int64_t)aeRun.getDataSliceId())
    {
        sprintf(buf, "test fails: 2 \n");
        aeFunc->log(NzaeFunction::LOG_DEBUG, buf);
    }

    if (txid != 0 && txid != (int64_t)aeRun.getTransactionId())
    {
        sprintf(buf, "test fails: 3 \n");
        aeFunc->log(NzaeFunction::LOG_DEBUG, buf);
    }

    if (hwid != (int64_t)aeRun.getHardwareId())
    {
        sprintf(buf, "test fails: 4 \n");
        aeFunc->log(NzaeFunction::LOG_DEBUG, buf);
    }

    if (nslices != (int64_t)aeRun.getNumberDataSlices())
    {
        sprintf(buf, "test fails: 5 \n");
        aeFunc->log(NzaeFunction::LOG_DEBUG, buf);
    }

    if (nspus != (int64_t)aeRun.getNumberSpus())
    {
        sprintf(buf, "test fails: 6 \n");
        aeFunc->log(NzaeFunction::LOG_DEBUG, buf);
    }
}

class MyHandler : public NzaeFunctionMessageHandler
{
public:
    void evaluate(NzaeFunction& api, NzaeRecord &input, NzaeRecord &result) {

        int64_t ar[6];

        for (int i=0; i < 6; i++)
        {
            nz::ae::NzaeField &fi = input.get(i);
            if (fi.type() == NzaeDataTypes::NZUDSUDX_INT64){
                ar[i] = (int64_t)(NzaeInt64Field&)fi;
            }
            else if (fi.type() == NzaeDataTypes::NZUDSUDX_INT32){
                ar[i] = (int32_t)(NzaeInt32Field&)fi;
            }
        }
        validateRuntime(&api, ar, NzaeRuntime::NZAE_ADAPTER_UDTF);

        std::string str = "done";

        NzaeStringField &f = (NzaeStringField&)result.get(0);
        f = str;
    }
};
static int run(NzaeFunction *aeFunc)
{
    aeFunc->run(new MyHandler());
    return 0;
}

Compilation

Use the standard compile:

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

Registration

Register the example using the --mem and --mask options. The --mask option enables logging for DEBUG and the --mem option sets the memory runtime information.

$NZ_EXPORT_DIR/ae/utilities/bin/register_ae \
     --sig "runtimeae(int8, int8, int8,int8,int8,int8)" \
     --return "table(output varchar(100))" \
     --language cpp --template udtf --exe runtimeae --version 3 \
     --mem 123 --mask debug

Running

Before running, enable logging by running nzudxdbg:

nzudxdbg
Processing 1 spus
.
done
Processing host
done

Run the query in nzsql:

SELECT * FROM TABLE WITH FINAL(runtimeae(1,1,1,1,1,1));
 OUTPUT
--------
 done
(1 row)

The NPS system logging appears in the window where the NPS system was started:

03-19-10 09:43:59 (dbos.3020) [d,udx ] test fails: 2
03-19-10 09:43:59 (dbos.3020) [d,udx ] test fails: 3
03-19-10 09:43:59 (dbos.3020) [d,udx ] test fails: 4

This is the expected output since the arguments specified did not match the runtime in those cases.