/* implementation of operators enterwormhole/leavewormhole */ #include "OpWormHole.h" #include #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 #include #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 = " enterwormhole []"; 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(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(elem.addr); temporalalgebra::IPoint* intime = static_cast (tuple->GetAttribute(ipointPos)); TupleIdentifier* tid = static_cast(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(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 []"; 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(local.addr); result = qp->ResultStorage(s); switch (message) { case OPEN: { if (localInfo) { delete localInfo; } std::string wormHoleId = (static_cast(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(local.addr); // // switch( message ){ // case OPEN:{ // FText* valveId = static_cast(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(args[2].addr); // CcInt* max_wait = static_cast(args[3].addr); // valvePtr = LeaveWormHolePtr ( // new RandomLeaveWormHole(min_wait->GetValue(), // max_wait->GetValue()) ); // } else if (valve_id == RemoteValveId) { // FText* remote_valve = static_cast(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