Files
secondo/Algebras/Temporal2/OpWormHole.cpp
2026-01-23 17:03:45 +08:00

429 lines
12 KiB
C++

/*
implementation of operators enterwormhole/leavewormhole
*/
#include "OpWormHole.h"
#include <tr1/memory>
#include "Operator.h"
#include "NestedList.h"
#include "QueryProcessor.h"
#include "StandardTypes.h"
#include "Stream.h"
#include "Algebras/FText/FTextAlgebra.h"
#include "Algebras/TupleIdentifier/TupleIdentifier.h"
#include "TypeMapUtils.h"
#include "Symbols.h"
#include "ListUtils.h"
#include <sstream>
#include <boost/interprocess/ipc/message_queue.hpp>
#include "Types.h"
extern NestedList* nl;
extern QueryProcessor* qp;
using namespace std;
using std::tr1::shared_ptr;
namespace temporal2algebra{
struct EnterWormHoleInfo : OperatorInfo {
EnterWormHoleInfo() : OperatorInfo() {
name = "enterwormhole";
signature = "stream(tuple(ipoint, tid)) x string -> int)";
syntax = "<incoming_stream> enterwormhole [<MyId>]";
meaning = "Copies a stream tuples to a different process"
" used to workaround transaction limitations.\n"
"Elements in the remote process can be retrieved by the"
" leavewormhole operator.\n"
"ATTENTION: the tuples must only contain ipoint and tid"
" in the given order - otherwise bad things may happen.";
}
};
ListExpr EnterWormHole_tm( ListExpr args ) {
cout << "EnterWormHole_tm(" << nl->ToString(args) << ")\n";
int numArgs = nl->ListLength(args);
if (numArgs != 2 ) {
stringstream s;
s << "expected 2 arguments, but got " << numArgs;
return listutils::typeError(s.str());
}
ListExpr streamType = nl->First(args);
if (!listutils::isStream(streamType)) {
return listutils::typeError(
"expected stream (ipoint, tid) as first"
" argument (incoming stream), but got "
+ nl->ToString(streamType));
}
ListExpr wormHoleId = nl->Second(args);
if (!FText::checkType(wormHoleId)) {
return listutils::typeError("expected " + FText::BasicType()
+ " as second argument (WormHole Id), but got "
+ nl->ToString(wormHoleId));
}
return NList(CcInt::BasicType()).listExpr();
}
int EnterWormHole_sf( ListExpr args ) {
cout << "EnterWormHole_sf(" << nl->ToString(args) << ")\n";
return 0;
}
int EnterWormHole_vm( Word* args,
Word& result,
int message,
Word& local,
Supplier s ) {
std::string wormHoleId = (static_cast<FText*>(args[1].addr))->GetValue();
std::string memQueueName = "Temporal2_OpWormHole_Queue_" + wormHoleId;
boost::interprocess::message_queue* memqueue = 0;
if (wormHoleId != "") { // use empty id for testing...
try {
cout << "creating MemQueue: " << memQueueName.c_str() << "\n";
memqueue = new boost::interprocess::message_queue(
boost::interprocess::create_only,
memQueueName.c_str(),
1000,
sizeof(QueueData2)
);
} catch (const boost::interprocess::interprocess_exception ex) {
cout << "MemQueue not created\n";
cout << ex.what();
memqueue = 0;
}
}
result = qp->ResultStorage(s);
int count = 0;
qp->Open(args[0].addr); // open the stream
Word elem;
qp->Request(args[0].addr, elem);
while ( qp->Received(args[0].addr) ){
++count;
if (memqueue) {
int ipointPos=0;
int tidPos = 1;
Tuple* tuple = static_cast<Tuple*>(elem.addr);
temporalalgebra::IPoint* intime =
static_cast<temporalalgebra::IPoint*>
(tuple->GetAttribute(ipointPos));
TupleIdentifier* tid =
static_cast<TupleIdentifier*>(tuple->GetAttribute(tidPos));
QueueData2 qdata;
Point p = intime->value;
Instant i = intime->instant;
qdata.x = p.GetX();
qdata.y = p.GetY();
qdata.t = i.ToDouble();
qdata.tid = tid->GetTid();
qdata.lastElement = false;
cout << qdata << endl;
memqueue->send(&qdata, sizeof(QueueData2), 0);
tuple->DeleteIfAllowed();
}
// elem->DeleteIfAllowed();
qp->Request(args[0].addr, elem);
}
if (memqueue) {
QueueData2 qdata;
qdata.lastElement = true;
memqueue->send(&qdata, sizeof(QueueData2), 0);
delete memqueue; // the queue will be removed in the receiving proc
}
CcInt* res = static_cast<CcInt*>(result.addr) ;
res->Set(true , count);
qp->Close(args[0].addr);
return 0;
}
ValueMapping EnterWormHole_vms[] =
{
EnterWormHole_vm
};
Operator* getEnterWormHoleOpPtr() {
Operator* op = new Operator(
EnterWormHoleInfo(),
EnterWormHole_vms,
EnterWormHole_sf,
EnterWormHole_tm
);
// op->SetUsesArgsInTypeMapping();
return op;
}
struct LeaveWormHoleInfo : OperatorInfo {
LeaveWormHoleInfo() : OperatorInfo() {
name = "leavewormhole";
signature = "string -> stream(alpha)";
syntax = "leavewormhole [<MyValveId>]";
meaning = "provides a stream from another secondo"
" process (via enterwormhole).";
}
};
ListExpr LeaveWormHole_tm( ListExpr args ) {
cout << "LeaveWormHole_tm(" << nl->ToString(args) << ")\n";
int numArgs = nl->ListLength(args);
if (numArgs != 1 ) {
stringstream s;
s << "expected 1 argument, but got " << numArgs;
return listutils::typeError(s.str());
}
ListExpr wormHoleIdType = nl->First(nl->First(args));
if (!FText::checkType(wormHoleIdType)) {
return listutils::typeError("expected " + FText::BasicType()
+ " as first argument (WormHole Id), but got "
+ nl->ToString(wormHoleIdType));
}
ListExpr wormHoleIdName = nl->Second(nl->First(args));
if (nl->AtomType(wormHoleIdName) != TextType) {
return listutils::typeError(
"expected TextType contents in second Argument, but got "
+ nl->ToString(wormHoleIdName));
}
std::string wormHoleId = nl->Text2String(wormHoleIdName);
cout << wormHoleId;
// connect to wormhole, read stream type and return that
NList tid_attr("DestTid", TupleIdentifier::BasicType());
NList intime_attr("IPos", Intime::BasicType());
NList attrs(tid_attr, intime_attr);
return NList().tupleStreamOf( attrs ).listExpr();
//return NList(CcInt::BasicType()).listExpr();
}
int LeaveWormHole_sf( ListExpr args ) {
cout << "LeaveWormHole_sf(" << nl->ToString(args) << ")\n";
return 0;
}
int LeaveWormHole_vm( Word* args,
Word& result,
int message,
Word& local,
Supplier s ) {
struct LocalInfo {
std::string qName;
boost::interprocess::message_queue* queue;
LocalInfo(std::string& memQueueName) :
qName(memQueueName),
queue(0) {
cout << "opening MemQueue: "
<< qName.c_str() << "\n";
try {
queue = new boost::interprocess::message_queue(
boost::interprocess::open_only,
qName.c_str()
);
} catch (const boost::interprocess::interprocess_exception ex) {
cout << "couldn't open MemQueue:\n";
cout << ex.what() << endl;
queue = 0;
}
}
~LocalInfo() {
if (queue) {
delete queue;
boost::interprocess::message_queue::remove(
qName.c_str());
}
}
};
LocalInfo* localInfo = static_cast<LocalInfo*>(local.addr);
result = qp->ResultStorage(s);
switch (message) {
case OPEN:
{
if (localInfo) {
delete localInfo;
}
std::string wormHoleId =
(static_cast<FText*>(args[0].addr))->GetValue();
std::string memQueueName = "Temporal2_OpWormHole_Queue_" + wormHoleId;
localInfo = new LocalInfo(memQueueName);
local.setAddr(localInfo);
if (!localInfo->queue) {
return CANCEL;
}
return 0;
break;
}
case REQUEST:
{
if (!localInfo->queue) {
cout << "no MemQueue with Data available\n";
return CANCEL;
}
size_t dummy_rcvd_size;
unsigned int dummy_prio;
QueueData2 qdata;
localInfo->queue->receive(
&qdata,
sizeof(QueueData2),
dummy_rcvd_size,
dummy_prio);
if (!qdata.lastElement) {
ListExpr tupleType = nl->Second(GetTupleResultType(s));
Tuple* res_tuple = new Tuple(tupleType);
TupleIdentifier* tid = new TupleIdentifier(true);
tid->SetTid(qdata.tid);
res_tuple->PutAttribute(0, tid);
Instant i(qdata.t);
Point p(qdata.x, qdata.y);
res_tuple->PutAttribute(1, new Intime(i,p));
result.setAddr(res_tuple);
return YIELD;
}
delete localInfo;
localInfo = 0;
local.setAddr(localInfo);
return CANCEL;
break;
}
case CLOSE:
if (localInfo) {
delete localInfo;
localInfo = 0;
local.setAddr(localInfo);
}
return 0;
break;
}
assert(false); //shouldn't get here. Unhandled message type
return -1;
}
// struct LeaveWormHole_LocalInfo{
// LeaveWormHole_LocalInfo(LeaveWormHolePtr valve): pValve(valve) {
// };
// LeaveWormHolePtr pValve;
// };
//
// Word elem;
// LeaveWormHole_LocalInfo *localInfo =
// static_cast<LeaveWormHole_LocalInfo*>(local.addr);
//
// switch( message ){
// case OPEN:{
// FText* valveId = static_cast<FText*>(args[1].addr);
// const std::string valve_id = valveId->GetValue();
// LeaveWormHolePtr valvePtr;
// if (valve_id == OpenValveId) {
// valvePtr = LeaveWormHolePtr(new OpenLeaveWormHole() );
// } else if (valve_id == RandomValveId) {
// CcInt* min_wait = static_cast<CcInt*>(args[2].addr);
// CcInt* max_wait = static_cast<CcInt*>(args[3].addr);
// valvePtr = LeaveWormHolePtr (
// new RandomLeaveWormHole(min_wait->GetValue(),
// max_wait->GetValue()) );
// } else if (valve_id == RemoteValveId) {
// FText* remote_valve = static_cast<FText*>(args[2].addr);
// valvePtr = LeaveWormHolePtr (
// RemoteLeaveWormHole::create(remote_valve->GetValue()) );
// } else {
// cout << "Unknown valveId: " << valve_id << endl;
// assert(false);
// }
//
// localInfo = new LeaveWormHole_LocalInfo(valvePtr);
//
// local.setAddr(localInfo);
// qp->Open(args[0].addr);
// return 0;
// }
// case REQUEST:{
// if(!localInfo){ return CANCEL; }
// localInfo->pValve->waitForSignal();
// qp->Request(args[0].addr, elem);
// while ( qp->Received(args[0].addr) ) {
// result = elem;
// localInfo->pValve->sendHasReadSucceeded(true);
// return YIELD;
// }
// localInfo->pValve->sendHasReadSucceeded(false);
// return CANCEL;
// }
// case CLOSE:{
// qp->Close(args[0].addr);
// if(localInfo){
// delete localInfo;
// local.setAddr(0);
// }
// return 0;
// }
// } // switch
// assert (false); // should not happen: unhandled message type
// }
ValueMapping LeaveWormHole_vms[] =
{
LeaveWormHole_vm
};
Operator* getLeaveWormHoleOpPtr() {
Operator* op = new Operator(
LeaveWormHoleInfo(),
LeaveWormHole_vms,
LeaveWormHole_sf,
LeaveWormHole_tm
);
op->SetUsesArgsInTypeMapping();
return op;
}
} // end of namespace temporal2algebra