C++ Beispiel (mehrere gleichzeitige Verbindungen)
In C++ gibt es zwei Möglichkeiten, mehrere gleichzeitige Verbindungen unabhängig voneinander zu behandeln. Die erste besteht darin, mit pthreads einen Thread für jeden dieser Threads zu erstellen. Die zweite Möglichkeit ist die Abspaltung eines neuen Prozesses, der die Verbindung bearbeitet, wie in diesem Beispiel gezeigt. Dieses Beispiel basiert auf dem Beispiel für den Shaper und Sizer, allerdings mit Änderungen am Hauptteil.
In diesem Beispiel wird getApi mit TRUE aufgerufen, um den Fork-Modus anzuzeigen und einen Zeiger statt einer Referenz zurückzubekommen. Im Remote-Modus gibt es zwei Prozesse. Der übergeordnete Prozess erhält einen NULL-Wert zurück, erhöht den Zähler des untergeordneten Prozesses und tut nichts; dies geschieht zweimal. Im Kindprozess nach der Abspaltung gibt getApi die API zurück, mit der ein Shaper oder Sizer gehandhabt werden soll, und beendet sich dann.
fork.cppCode erstellen
#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;
}
Kompilierung
Kompilieren Sie wie folgt:
$NZ_EXPORT_DIR/ae/utilities/bin/compile_ae --language cpp --template compile \
--exe forkae --compargs "-g -Wall" --linkargs "-g" fork.cpp --version 3
Registrierung
Verwenden Sie für die Registrierung eine Remote-Variante, um den Fork-Modus zu demonstrieren, der nur im Remote-Modus funktioniert:
$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
Aktiv
Zum Laufen:
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)