Información de registro y tiempo de ejecución en lenguaje C
Este ejemplo utiliza el siguiente nombre de archivo:log.c
Código
El código de este ejemplo explora funcionalidades que pueden no ser de uso común. El registro se puede utilizar para ayudar a rastrear la ejecución de un AE. Para que sea útil, el AE debe estar registrado con una máscara de registro y el registro debe estar habilitado a través de nzudxdbg. Para recibir mensajes de registro del sistema en la ventana donde se inició el sistema NPS, es necesario iniciar NPS con la opción '-i' ' (por ejemplo, 'nzstart -i'). Esto hace que los procesos NPS permanezcan unidos al terminal. La información de tiempo de ejecución proporciona estadísticas sobre el sistema NPS, incluyendo el número de dataslices, el número de SPUs y el locus de ejecución.
#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;
}
Una compilación
$NZ_EXPORT_DIR/ae/utilities/bin/compile_ae --language system --version 3 \
--template compile log.c --exe logRegistro
Registra el ejemplo utilizando las opciones --mem y --mask. La opción --mask activa el registro para DEBUG y la opción --mem establece la información de tiempo de ejecución de memoria.
$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 ejecución
Antes de ejecutarlo, active el registro ejecutando nzudxdbg:
nzudxdbg
Processing 1 spus
.
done
Processing host
done
A continuación, ejecute el SQL:
SELECT * FROM TABLE WITH FINAL(runtime_c(1,1,1,1,1,1));
OUTPUT
--------
done
(1 row)
El registro del sistema NPS aparece en la ventana donde se inició el sistema NPS:
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
Esta es la salida esperada, ya que los argumentos especificados no coincidían con el tiempo de ejecución en esos casos.