void process()
    {
        helper->clearAggregate(aggy);
        input = inputs.item(0);
        startInput(input);
        processed = THORDATALINK_STARTED;

        try
        {
            while (!abortSoon)
            {
                OwnedConstThorRow row(input->ungroupedNextRow());
                if (!row)
                    break;
                helper->process(aggy, row);     
                processed++;
            }
            ActPrintLog("DISTRIBUTION: processed %"RCPF"d records", processed & THORDATALINK_COUNT_MASK);
        }
        catch(CATCHALL)
        {
            ActPrintLog("DISTRIBUTION: exception");
            throw;
        }
        CMessageBuffer msg;
        helper->serialize(aggy, msg);
        container.queryJob().queryJobComm().send(msg, 0, mpTag);
    }
    void kill()
    {
        CSlaveActivity::kill();

        helper->destruct(aggy);
        ma.clear();
    }
    virtual void process()
    {
        CMasterActivity::process();

        IHThorDistributionArg * helper = (IHThorDistributionArg *)queryHelper();
        IOutputMetaData *rcSz = helper->queryInternalRecordSize();

        unsigned nslaves = container.queryJob().querySlaves();

        IDistributionTable * * result = (IDistributionTable * *)createThorRow(rcSz->getMinRecordSize()); // not a real row
        helper->clearAggregate(result);


        while (nslaves--)
        {
            rank_t sender;
            CMessageBuffer msg;
            if (!receiveMsg(msg, RANK_ALL, mpTag, &sender))
                return;
#if THOR_TRACE_LEVEL >= 5
            ActPrintLog("Received distribution result from node %d", (unsigned)sender);
#endif
            if (msg.length())
                helper->merge(result, msg);
        }

        StringBuffer tmp;
        tmp.append("<XML>");
        helper->gatherResult(result, tmp);
        tmp.append("</XML>");

#if THOR_TRACE_LEVEL >= 5
        ActPrintLog("Distribution result: %s", tmp.str());
#endif

        helper->sendResult(tmp.length(), tmp.str());

        destroyThorRow(result);
    }
 void init(MemoryBuffer &data, MemoryBuffer &slaveData)
 {
     mpTag = container.queryJob().deserializeMPTag(data);
     helper = static_cast <IHThorDistributionArg *> (queryHelper()); 
     aggy = (IDistributionTable * *)ma.allocate(helper->queryInternalRecordSize()->getMinRecordSize());
 }