Informations relatives à la journalisation et à l'exécution en langage C

Cet exemple utilise le nom de fichier suivant :log.c

Coder

Le code de cet exemple explore des fonctionnalités qui ne sont pas forcément utilisées couramment. La journalisation peut être utilisée pour retracer l'exécution d'un AE. Pour être utile, l'AE doit être enregistré avec un masque de journalisation et la journalisation doit être activée via nzudxdbg. Pour recevoir les messages de journalisation du système dans la fenêtre où le système NPS a été démarré, vous devez démarrer NPS avec l'option '-i' (par exemple, "nzstart -i'). Les processus NPS restent ainsi attachés au terminal. Les informations sur l'exécution fournissent des statistiques sur le système NPS, notamment le nombre de tranches de données, le nombre de SPU et le lieu d'exécution.

#include <stdio.h>
#include <stdlib.h>

#include "nzaeapis.h"

static int run(NZAE_HANDLE h);
int main(int argc, char * argv[])
{
    if (nzaeIsLocal())
    {
        NzaeInitialization arg;
        memset(&arg, 0, sizeof(arg));
            arg.ldkVersion = NZAE_LDK_VERSION;
        if (nzaeInitialize(&arg))
        {
            fprintf(stderr, "initialization failed\n");
            return -1;
        }
        run(arg.handle);
        nzaeClose(arg.handle);
    }
    else {
        NZAECONPT_HANDLE hConpt = nzaeconptCreate();
        if (!hConpt)
        {
            fprintf(stderr, "error creating connection point\n");
            fflush(stderr);
            return -1;
        }
        const char * conPtName = nzaeRemprotGetRemoteName();
        if (!conPtName)
        {
            fprintf(stderr, "error getting connection point name\n");
            fflush(stderr);
            exit(-1);
        }
        if (nzaeconptSetName(hConpt, conPtName))
        {
            fprintf(stderr, "error setting connection point name\n");
            fflush(stderr);
            nzaeconptClose(hConpt);
            return -1;
        }
        NzaeremprotInitialization args;
        memset(&args, 0, sizeof(args));
        args.ldkVersion = NZAE_LDK_VERSION;
        args.hConpt = hConpt;
        if (nzaeRemprotCreateListener(&args))
        {
            fprintf(stderr, "unable to create listener - %s\n", \
                args.errorMessage);
            fflush(stderr);
            nzaeconptClose(hConpt);
            return -1;
        }
        NZAEREMPROT_HANDLE hRemprot = args.handle;
        NzaeApi api;
        int i;
        for (i = 0; i < 5; i++)
        {
            if (nzaeRemprotAcceptApi(hRemprot, &api))
            {
                fprintf(stderr, "unable to accept API - %s\n", \
                    nzaeRemprotGetLastErrorText(hRemprot));
                fflush(stderr);
                nzaeconptClose(hConpt);
                nzaeRemprotClose(hRemprot);
                return -1;
            }
            if (api.apiType != NZAE_API_FUNCTION)
            {
                fprintf(stderr, "unexpected API returned\n");
                fflush(stderr);
                nzaeconptClose(hConpt);
                nzaeRemprotClose(hRemprot);
                return -1;
            }
            printf("testcapi: accepted a remote request\n");
            fflush(stdout);
            run(api.handle.function);
        }
        nzaeRemprotClose(hRemprot);
        nzaeconptClose(hConpt);
     }
     return 0;
}

static void validateRuntime(NZAE_HANDLE handle, NzaeRuntime *aeRun, 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];
    char buf[1024];

    if (locus != (int64_t)aeRun->locus)
    {
        sprintf(buf, "test fails: 1\n");
        nzaeLog(handle,NZAE_LOG_DEBUG, buf);
    }
    if (aeRun->suggestedMemoryLimit != 123)
    {
        sprintf(buf, "test fails: 7 \n");
        nzaeLog(handle,NZAE_LOG_DEBUG, buf);
    }
    if (aeRun->userQuery == false)
    {
        sprintf(buf, "test fails: 8 \n");
        nzaeLog(handle,NZAE_LOG_DEBUG, buf);
    }
    if (type != (int64_t)aeRun->adapterType)
    {
        sprintf(buf, "test fails: 9 \n");
        nzaeLog(handle,NZAE_LOG_DEBUG, buf);
    }
    if (locus == (int64_t)NZAE_LOCUS_POSTGRES) 
    {
        return;
    }
    if (dataslice != (int64_t)aeRun->dataSliceId)
    {
        sprintf(buf, "test fails: 2 \n");
        nzaeLog(handle,NZAE_LOG_DEBUG, buf);
    }
    if (txid != 0 && txid != (int64_t)aeRun->transactionId)
    {
        sprintf(buf, "test fails: 3 \n");
        nzaeLog(handle,NZAE_LOG_DEBUG, buf);
    }
    if (hwid != (int64_t)aeRun->hardwareId)
    {
        sprintf(buf, "test fails: 4 \n");
        nzaeLog(handle,NZAE_LOG_DEBUG, buf);
    }
    if (nslices != (int64_t)aeRun->numberDataSlices)
    {
        sprintf(buf, "test fails: 5 \n");
        nzaeLog(handle,NZAE_LOG_DEBUG, buf);
    }
    if (nspus != (int64_t)aeRun->numberSpus)
    {
        sprintf(buf, "test fails: 6 \n");
        nzaeLog(handle,NZAE_LOG_DEBUG, buf);
    }
}

static int run(NZAE_HANDLE h)
{
    NzaeMetadata metadata;
    if (nzaeGetMetadata(h, &metadata))
    {
        fprintf(stderr, "get metadata failed\n");
        return -1;
    }

    #define CHECK(value) \
    { \
        NzaeRcCode rc = value; \
        if (rc) \
        { \
            const char * format = "%s in %s at %d"; \
            fprintf(stderr, format, \
                nzaeGetLastErrorText(h), __FILE__, __LINE__); \
            nzaeUserError(h, format, \
                nzaeGetLastErrorText(h), __FILE__, __LINE__); \
            exit(-1); \
        } \
    }

    for (;;)
    {
        int64_t ar[6];
        int i;
        double result = 0;
        NzaeRcCode rc = nzaeGetNext(h);
        if (rc == NZAE_RC_END)
        {
            break;
        }

        NzudsData * input = NULL;
        for (i=0; i < 6; i++) {
            CHECK(nzaeGetInputColumn(h, i, &input));
            if (input->type == NZUDSUDX_INT32)
            {
                ar[i] = *input->data.pInt32;
            }
            else if (input->type == NZUDSUDX_INT64)
            {
                ar[i] = *input->data.pInt64;
            }
        }
        NzaeRuntime aeRun;
        nzaeGetRuntime(h,&aeRun);
        validateRuntime(h, &aeRun, ar, NZAE_ADAPTER_UDTF);
        CHECK(nzaeSetOutputString(h, 0, "done"));
        CHECK(nzaeOutputResult(h));
    }
    nzaeDone(h);
    return 0;
}

Compilation

Utiliser la compilation standard :
$NZ_EXPORT_DIR/ae/utilities/bin/compile_ae --language system --version 3 \
     --template compile log.c --exe log

Enregistrement

Enregistrez l'exemple en utilisant les options --mem et --mask. L'option --mask active la journalisation pour DEBUG et l'option --mem définit les informations sur la durée d'exécution de la mémoire.

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

En cours d'exécution

Avant de commencer, activez la journalisation en exécutant nzudxdbg:

nzudxdbg
Processing 1 spus
.
done
Processing host
done

Exécutez ensuite le code SQL :

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

L'enregistrement du système NPS apparaît dans la fenêtre où le système NPS a été démarré :

05-03-10 15:03:12 (dbos.18728) [d,udx ] test fails: 2
05-03-10 15:03:12 (dbos.18728) [d,udx ] test fails: 3
05-03-10 15:03:12 (dbos.18728) [d,udx ] test fails: 4

C'est la sortie attendue puisque les arguments spécifiés ne correspondaient pas à la durée d'exécution dans ces cas.