//
// (C) Copyright 2011-2013 Sergey A. Babkin.
// This file is a part of Triceps.
// See the file COPYRIGHT for the copyright notice and license information
//
// The context for an aggregator handler call.
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include "TricepsPerl.h"
#include "WrapAggregatorContext.h"
// The idea here is to combine multiple C++ structures that are used only in
// an aggregator handler call into a insgle Perl object, thus simplifying the
// API for the Perl aggregators.
namespace TRICEPS_NS
{
namespace TricepsPerl
{
WrapMagic magicWrapAggregatorContext = { "AggCtx" };
}; // Triceps::TricepsPerl
}; // Triceps
MODULE = Triceps::AggregatorContext PACKAGE = Triceps::AggregatorContext
###################################################################################
int
CLONE_SKIP(...)
CODE:
RETVAL = 1;
OUTPUT:
RETVAL
#// can not use the common typemap, because the destruction can be legally
#// called on an invalidated object, which would not pass the typemap
void
DESTROY(SV *selfsv)
CODE:
WrapAggregatorContext *self;
if( sv_isobject(selfsv) && (SvTYPE(SvRV(selfsv)) == SVt_PVMG) ) {
self = (WrapAggregatorContext *)SvIV((SV*)SvRV( selfsv ));
if (self == 0 || self->badMagic()) {
warn( "Triceps::AggregatorContext::DESTROY: self has an incorrect magic for WrapAggregatorContext" );
XSRETURN_UNDEF;
}
} else{
warn( "Triceps::AggregatorContext::DESTROY: self is not a blessed SV reference to WrapAggregatorContext" );
XSRETURN_UNDEF;
}
// warn("AggregatorContext %p destroyed!", self);
delete self;
#// get the number of rows in the group
int
groupSize(WrapAggregatorContext *self)
CODE:
clearErrMsg();
RETVAL = self->getParentIdxType()->groupSize(self->getGroupHandle());
OUTPUT:
RETVAL
#// get the row type of the result
WrapRowType *
resultType(WrapAggregatorContext *self)
CODE:
clearErrMsg();
// for casting of return value
static char CLASS[] = "Triceps::RowType";
RETVAL = new WrapRowType(const_cast<RowType *>(self->getGadget()->getLabel()->getType()));
OUTPUT:
RETVAL
#// iteration on the group
#// RowHandle with NULL pointer in it is used for the end-iterator
WrapRowHandle *
begin(WrapAggregatorContext *self)
CODE:
static char CLASS[] = "Triceps::RowHandle";
clearErrMsg();
Table *t = self->getTable();
Index *idx = self->getIndex();
RETVAL = new WrapRowHandle(t, idx->begin());
OUTPUT:
RETVAL
WrapRowHandle *
next(WrapAggregatorContext *self, WrapRowHandle *wcur)
CODE:
static char CLASS[] = "Triceps::RowHandle";
RETVAL = NULL; // shut up the warning
try { do {
clearErrMsg();
Table *t = self->getTable();
Index *idx = self->getIndex();
RowHandle *cur = wcur->get(); // NULL is OK
static char funcName[] = "Triceps::AggregatorContext::next";
if (wcur->ref_.getTable() != t) {
throw TRICEPS_NS::Exception(strprintf("%s: row argument is a RowHandle in a wrong table %s",
funcName, wcur->ref_.getTable()->getName().c_str()), false);
}
RETVAL = new WrapRowHandle(t, idx->next(cur));
} while(0); } TRICEPS_CATCH_CROAK;
OUTPUT:
RETVAL
WrapRowHandle *
last(WrapAggregatorContext *self)
CODE:
static char CLASS[] = "Triceps::RowHandle";
clearErrMsg();
Table *t = self->getTable();
Index *idx = self->getIndex();
RETVAL = new WrapRowHandle(t, idx->last());
OUTPUT:
RETVAL
#// translation to the group in another index: can be done in Perl
#// but more efficient and easier to push it into C++
WrapRowHandle *
beginIdx(WrapAggregatorContext *self, WrapIndexType *widx)
CODE:
static char CLASS[] = "Triceps::RowHandle";
RETVAL = NULL; // shut up the warning
try { do {
clearErrMsg();
Table *t = self->getTable();
Index *myidx = self->getIndex();
RowHandle *sample = myidx->begin();
if (sample == NULL) {
RETVAL = new WrapRowHandle(t, NULL);
} else {
IndexType *idx = widx->get();
static char funcName[] = "Triceps::AggregatorContext::beginIdx";
if (idx->getTabtype() != t->getType()) {
throw TRICEPS_NS::Exception(strprintf("%s: indexType argument does not belong to table's type", funcName), false);
}
RETVAL = new WrapRowHandle(t, t->firstOfGroupIdx(idx, sample));
}
} while(0); } TRICEPS_CATCH_CROAK;
OUTPUT:
RETVAL
#// translation to the group in another index: can be done in Perl
#// but more efficient and easier to push it into C++
WrapRowHandle *
endIdx(WrapAggregatorContext *self, WrapIndexType *widx)
CODE:
static char CLASS[] = "Triceps::RowHandle";
RETVAL = NULL; // shut up the warning
try { do {
clearErrMsg();
Table *t = self->getTable();
Index *myidx = self->getIndex();
RowHandle *sample = myidx->begin();
if (sample == NULL) {
RETVAL = new WrapRowHandle(t, NULL);
} else {
IndexType *idx = widx->get();
static char funcName[] = "Triceps::AggregatorContext::beginIdx";
if (idx->getTabtype() != t->getType()) {
throw TRICEPS_NS::Exception(strprintf("%s: indexType argument does not belong to table's type", funcName), false);
}
RETVAL = new WrapRowHandle(t, t->nextGroupIdx(idx, sample));
}
} while(0); } TRICEPS_CATCH_CROAK;
OUTPUT:
RETVAL
#// translation to the group in another index: can be done in Perl
#// but more efficient and easier to push it into C++
WrapRowHandle *
lastIdx(WrapAggregatorContext *self, WrapIndexType *widx)
CODE:
static char CLASS[] = "Triceps::RowHandle";
RETVAL = NULL; // shut up the warning
try { do {
clearErrMsg();
Table *t = self->getTable();
Index *myidx = self->getIndex();
RowHandle *sample = myidx->begin();
if (sample == NULL) {
RETVAL = new WrapRowHandle(t, NULL);
} else {
IndexType *idx = widx->get();
static char funcName[] = "Triceps::AggregatorContext::lastIdx";
if (idx->getTabtype() != t->getType()) {
throw TRICEPS_NS::Exception(strprintf("%s: indexType argument does not belong to table's type", funcName), false);
}
RETVAL = new WrapRowHandle(t, t->lastOfGroupIdx(idx, sample));
}
} while(0); } TRICEPS_CATCH_CROAK;
OUTPUT:
RETVAL
#// returns 1 on success, undef on error;
#// enqueueing mode is taken from the aggregator gadget
int
send(WrapAggregatorContext *self, SV *opcode, WrapRow *row)
CODE:
static char funcName[] = "Triceps::AggregatorContext::send";
try { do {
clearErrMsg();
Label *lab = self->getGadget()->getLabel();
const RowType *lt = lab->getType();
const RowType *rt = row->ref_.getType();
Row *r = row->ref_.get();
if ((lt != rt) && !lt->match(rt)) {
throw TRICEPS_NS::Exception(
strprintf("%s: row types do not match\n Label:\n ", funcName)
+ lt->print(" ") + "\n Row:\n " + rt->print(" "),
false
);
}
Rowop::Opcode op;
if (!parseOpcode(funcName, opcode, op))
break;
self->getGadget()->sendDelayed(self->getDest(), r, op);
} while(0); } TRICEPS_CATCH_CROAK;
RETVAL = 1;
OUTPUT:
RETVAL