void LocationService::handleLocationUpdateSubstreamRead(const UUID& source, SSTStreamPtr s, std::stringstream* prevdata, uint8* buffer, int length) { prevdata->write((const char*)buffer, length); String payload(prevdata->str()); if (locationUpdate(source, (void*)payload.c_str(), payload.size())) { // FIXME we should be getting a callback on stream close instead of // relying on this parsing as an indicator delete prevdata; // Clear out callback so we aren't responsible for any remaining // references to s, and close the stream s->registerReadCallback(0); s->close(false); } }
void AlwaysLocationUpdatePolicy::tryCreateChildStream(SSTStreamPtr parent_stream, std::string* msg, int count) { parent_stream->createChildStream( std::tr1::bind(&AlwaysLocationUpdatePolicy::locSubstreamCallback, this, _1, _2, parent_stream, msg, count+1), (void*)msg->data(), msg->size(), OBJECT_PORT_LOCATION, OBJECT_PORT_LOCATION ); }
void LocationService::handleLocationUpdateSubstream(const UUID& source, int err, SSTStreamPtr s) { s->registerReadCallback( std::tr1::bind( &LocationService::handleLocationUpdateSubstreamRead, this, source, s, new std::stringstream(), std::tr1::placeholders::_1,std::tr1::placeholders::_2 ) ); }
void AlwaysLocationUpdatePolicy::locSubstreamCallback(int x, SSTStreamPtr substream, SSTStreamPtr parent_stream, std::string* msg, int count) { // If we got it, the data got sent and we can drop the stream if (substream) { delete msg; substream->close(false); return; } // If we didn't get it and we haven't retried too many times, try // again. Otherwise, report error and give up. if (count < 5) { tryCreateChildStream(parent_stream, msg, count); } else { SILOG(always_loc,error,"Failed multiple times to open loc update substream."); delete msg; } }
void HostedObject::sendLocUpdateRequest(const SpaceID& space, const ObjectReference& oref) { // Up here to avoid recursive lock ProxyObjectPtr self_proxy = getProxy(space, oref); Mutex::scoped_lock locker(presenceDataMutex); assert(mPresenceData.find(SpaceObjectReference(space, oref)) != mPresenceData.end()); PerPresenceData& pd = *(mPresenceData.find(SpaceObjectReference(space, oref)))->second; if (!self_proxy) { HO_LOG(warn,"Requesting sendLocUpdateRequest for missing self proxy. Doing nothing."); return; } assert(pd.updateFields != PerPresenceData::LOC_FIELD_NONE); // Generate and send an update to Loc Protocol::Loc::Container container; Protocol::Loc::ILocationUpdateRequest loc_request = container.mutable_update_request(); uint64 epoch = pd.requestEpoch++; loc_request.set_epoch(epoch); if (pd.updateFields & PerPresenceData::LOC_FIELD_LOC) { Protocol::ITimedMotionVector requested_loc = loc_request.mutable_location(); requested_loc.set_t( spaceTime(space, pd.requestLoc->location().updateTime()) ); requested_loc.set_position(pd.requestLoc->location().position()); requested_loc.set_velocity(pd.requestLoc->location().velocity()); // Save value but bump the epoch pd.requestLoc->setLocation(pd.requestLoc->location(), epoch); } if (pd.updateFields & PerPresenceData::LOC_FIELD_ORIENTATION) { Protocol::ITimedMotionQuaternion requested_orient = loc_request.mutable_orientation(); requested_orient.set_t( spaceTime(space, pd.requestLoc->orientation().updateTime()) ); //Normalize positions, which only make sense as unit quaternions. requested_orient.set_position(pd.requestLoc->orientation().position().normal()); requested_orient.set_velocity(pd.requestLoc->orientation().velocity()); // Save value but bump the epoch pd.requestLoc->setOrientation(pd.requestLoc->orientation(), epoch); } if (pd.updateFields & PerPresenceData::LOC_FIELD_BOUNDS) { loc_request.set_bounds(pd.requestLoc->bounds()); // Save value but bump the epoch pd.requestLoc->setBounds(pd.requestLoc->bounds(), epoch); } if (pd.updateFields & PerPresenceData::LOC_FIELD_MESH) { loc_request.set_mesh(pd.requestLoc->mesh().toString()); // Save value but bump the epoch pd.requestLoc->setMesh(pd.requestLoc->mesh(), epoch); } if (pd.updateFields & PerPresenceData::LOC_FIELD_PHYSICS) { loc_request.set_physics(pd.requestLoc->physics()); // Save value but bump the epoch pd.requestLoc->setPhysics(pd.requestLoc->physics(), epoch); } std::string payload = serializePBJMessage(container); bool send_succeeded = false; SSTStreamPtr spaceStream = mObjectHost->getSpaceStream(space, oref); if (spaceStream) { spaceStream->createChildStream( std::tr1::bind(discardChildStream, _1, _2), (void*)payload.data(), payload.size(), OBJECT_PORT_LOCATION, OBJECT_PORT_LOCATION ); send_succeeded = true; } if (send_succeeded) { pd.updateFields = PerPresenceData::LOC_FIELD_NONE; } else { // Set up retry timer. Just rerun this method, but add no new // update fields. pd.rerequestTimer->wait( Duration::milliseconds((int64)10), std::tr1::bind(&HostedObject::sendLocUpdateRequest, this, space, oref) ); } }