void HostedObject::iHandleDisconnected( const HostedObjectWPtr& weakSelf, const SpaceObjectReference& spaceobj, Disconnect::Code cc) { HostedObjectPtr self(weakSelf.lock()); if ((!self)||self->stopped()) { HO_LOG(detailed,"Ignoring disconnection callback after system stop requested."); return; } Mutex::scoped_lock lock(self->notifyMutex); self->notify(&SessionEventListener::onDisconnected, self, spaceobj); // Only invoke disconnectFromSpace if we weren't already aware of the // disconnection, i.e. if the disconnect was due to the space and we haven't // cleaned up yet. if (cc == Disconnect::Forced) self->disconnectFromSpace(spaceobj.space(), spaceobj.object()); if (cc == Disconnect::LoginDenied) { assert(self->mPresenceData.find(spaceobj)==self->mPresenceData.end()); self->mObjectHost->unregisterHostedObject(spaceobj, self.get()); if (--self->mNumOutstandingConnections==0&&self->mDestroyWhenConnected) { self->mDestroyWhenConnected=false; self->destroy(true); } } }
void LocationService::newSession(ObjectSession* session) { using std::tr1::placeholders::_1; using std::tr1::placeholders::_2; SST::Stream<SpaceObjectReference>::Ptr strm = session->getStream(); SST::Connection<SpaceObjectReference>::Ptr conn = strm->connection().lock(); assert(conn); SpaceObjectReference sourceObject = conn->remoteEndPoint().endPoint; // Datagram updates conn->registerReadDatagramCallback( OBJECT_PORT_LOCATION, std::tr1::bind( &LocationService::handleLocationUpdateDatagram, this, sourceObject.object().getAsUUID(), std::tr1::placeholders::_1,std::tr1::placeholders::_2 ) ); // SST updates strm->listenSubstream(OBJECT_PORT_LOCATION, std::tr1::bind( &LocationService::handleLocationUpdateSubstream, this, sourceObject.object().getAsUUID(), std::tr1::placeholders::_1,std::tr1::placeholders::_2 ) ); }
ProxyObjectPtr ObjectHostProxyManager::getProxyObject(const SpaceObjectReference &id) const { if (id.space() == mSpaceID) { ProxyMap::const_iterator iter = mProxyMap.find(id.object()); if (iter != mProxyMap.end()) { return (*iter).second.obj; } } return ProxyObjectPtr(); }
ProxyObjectPtr ProxyManager::getProxyObject(const SpaceObjectReference &id) const { PROXYMAN_SERIALIZED(); assert(id.space() == mID.space()); ProxyMap::const_iterator iter = mProxyMap.find(id.object()); if (iter != mProxyMap.end()) return (*iter).second.ptr; return ProxyObjectPtr(); }
void ObjectHost::wrappedStreamCreatedCallback(HostedObjectWPtr ho_weak, const SpaceObjectReference& sporef, SessionManager::ConnectionEvent after, StreamCreatedCallback cb) { if (mQueryProcessor != NULL) { HostedObjectPtr ho(ho_weak); if (ho) { SSTStreamPtr strm = getSpaceStream(sporef.space(), sporef.object()); // This had better be OK here since we're just getting the callback assert(strm); mQueryProcessor->presenceConnectedStream(ho, sporef, strm); } } cb(sporef, after); }
void HostedObject::handleLocationUpdate(const SpaceObjectReference& observer, const LocUpdate& lu) { ProxyManagerPtr proxy_manager = this->getProxyManager(observer.space(), observer.object()); if (!proxy_manager) { HO_LOG(warn,"Hosted Object received a message for a presence without a proxy manager."); return; } SpaceObjectReference observed(observer.space(), ObjectReference(lu.object())); ProxyObjectPtr proxy_obj = proxy_manager->getProxyObject(observed); assert(proxy_obj); this->processLocationUpdate( observer, proxy_obj, lu); }
SharedResourcePtr GraphicsResourceManager::getResourceEntity(const SpaceObjectReference &id, GraphicsEntity *graphicsEntity) { WeakResourcePtr curWeakPtr = getResource(id.toString()); SharedResourcePtr curSharedPtr = curWeakPtr.lock(); if (curSharedPtr) return curSharedPtr; else { curSharedPtr = GraphicsResource::construct<GraphicsResourceEntity>(id, graphicsEntity); mIDResourceMap[id.toString()] = curSharedPtr; mEntities.insert(curSharedPtr.get()); return curSharedPtr; } }
void OrphanLocUpdateManager::addOrphanUpdate(const SpaceObjectReference& observed, const Sirikata::Protocol::Loc::LocationUpdate& update) { assert( ObjectReference(update.object()) == observed.object() ); UpdateInfoList& info_list = mUpdates[observed]; info_list.push_back( UpdateInfoPtr(new UpdateInfo(observed, new Sirikata::Protocol::Loc::LocationUpdate(update), mContext->simTime() + mTimeout)) ); }
void ObjectHostProxyManager::destroyViewedObject(const SpaceObjectReference &newObj, QueryTracker*viewer) { ProxyMap::iterator iter = mProxyMap.find(newObj.object()); if (iter != mProxyMap.end()) { std::tr1::unordered_multiset<QueryTracker*>::iterator viewiter; viewiter = iter->second.viewers.find(viewer); iter->second.viewers.erase(viewiter); viewiter = iter->second.viewers.find(viewer); if (viewiter == iter->second.viewers.end()) { iter->second.obj->destroy(); notify(&ProxyCreationListener::onDestroyProxy,iter->second.obj); mProxyMap.erase(iter); } } }
void HostedObject::handleStreamCreated(const HostedObjectWPtr& weakSelf, const SpaceObjectReference& spaceobj, SessionManager::ConnectionEvent after, PresenceToken token) { HO_LOG(detailed,"Handling new SST stream from space server for " << spaceobj); HostedObjectPtr self(weakSelf.lock()); if (!self) return; Mutex::scoped_lock lock(self->notifyMutex); HO_LOG(detailed,"Notifying of connected object " << spaceobj.object() << " to space " << spaceobj.space()); if (after == SessionManager::Connected) { self->notify(&SessionEventListener::onConnected, self, spaceobj, token); if (--self->mNumOutstandingConnections==0&&self->mDestroyWhenConnected) { self->mDestroyWhenConnected=false; self->destroy(true); } } else if (after == SessionManager::Migrated) self->notify(&SessionEventListener::onMigrated, self, spaceobj, token); }
void invokeOrphanUpdates(ObjectHost* oh, const QuerierIDType& observer, const SpaceObjectReference& proximateID, ListenerType* listener) { ObjectUpdateMap::iterator it = mUpdates.find(proximateID); if (it == mUpdates.end()) return; const UpdateInfoList& info_list = it->second; for(UpdateInfoList::const_iterator info_it = info_list.begin(); info_it != info_list.end(); info_it++) { if ((*info_it)->value != NULL) { LocProtocolLocUpdate llu( *((*info_it)->value), oh, proximateID.space() ); listener->onOrphanLocUpdate( observer, llu ); } else if ((*info_it)->opd != NULL) { PresencePropertiesLocUpdate plu( (*info_it)->object.object(), *((*info_it)->opd) ); listener->onOrphanLocUpdate( observer, plu ); } } // Once we've notified of these we can get rid of them -- if they // need the info again they should re-register it with // addUpdateFromExisting before cleaning up the object. mUpdates.erase(it); }
ProxyObjectPtr HostedObject::createProxy(const SpaceObjectReference& objref, const SpaceObjectReference& owner_objref, const Transfer::URI& meshuri, TimedMotionVector3f& tmv, TimedMotionQuaternion& tmq, const BoundingSphere3f& bs, const String& phy, const String& query, bool isAggregate, uint64 seqNo) { ProxyManagerPtr proxy_manager = getProxyManager(owner_objref.space(), owner_objref.object()); Mutex::scoped_lock lock(presenceDataMutex); if (!proxy_manager) { mPresenceData.insert( PresenceDataMap::value_type( owner_objref, new PerPresenceData(getSharedPtr(), owner_objref.space(),owner_objref.object(), BaseDatagramLayerPtr(), query) ) ); proxy_manager = getProxyManager(owner_objref.space(), owner_objref.object()); } ProxyObjectPtr proxy_obj = proxy_manager->createObject(objref, tmv, tmq, bs, meshuri, phy, isAggregate, seqNo); return proxy_obj; }
void ManualObjectQueryProcessor::registerOrUpdateObjectQuery(const SpaceObjectReference& sporef) { // Get query info ObjectStateMap::iterator it = mObjectState.find(sporef); assert(it != mObjectState.end()); ObjectState& state = it->second; HostedObjectPtr ho = state.who.lock(); assert( ho && !state.query.empty() && state.node != OHDP::NodeID::null() ); // Get the appropriate handler QueryHandlerMap::iterator handler_it = mObjectQueryHandlers.find(OHDP::SpaceNodeID(sporef.space(), state.node)); assert(handler_it != mObjectQueryHandlers.end()); ObjectQueryHandlerPtr handler = handler_it->second; // And register handler->updateQuery(ho, sporef, state.query); state.registered = true; }
ProxyObjectPtr ProxyManager::createObject( const SpaceObjectReference& id, const TimedMotionVector3f& tmv, const TimedMotionQuaternion& tmq, const AggregateBoundingInfo& bs, const Transfer::URI& meshuri, const String& phy, bool isAggregate, uint64 seqNo ) { PROXYMAN_SERIALIZED(); ProxyObjectPtr newObj; // Try to reuse an existing object, even if we only have a valid // weak pointer to it. assert(id.space() == mID.space()); ProxyMap::iterator iter = mProxyMap.find(id.object()); if (iter != mProxyMap.end()) { // From strong ref newObj = iter->second.ptr; if (!newObj) { // From weak ref newObj = iter->second.wptr.lock(); // And either update the strong ref or clear out the entry // if its not even valid anymore. if (newObj) iter->second.ptr = newObj; else mProxyMap.erase(iter); } } // If we couldn't get a valid existing copy, create and insert a // new one. if (!newObj) { newObj = ProxyObject::construct(getSharedPtr(), id); std::pair<ProxyMap::iterator, bool> result = mProxyMap.insert( ProxyMap::value_type( newObj->getObjectReference().object(), ProxyData(newObj) ) ); iter = result.first; } assert(newObj); assert(newObj->getObjectReference() == id); assert(newObj->getOwner().get() == this); // This makes things simpler elsewhere: For new objects, we ensure // all the values are set properly so that when the notification // happens below, the proxy passed to listeners (for // onCreateProxy) will be completely setup, making it valid for // use. We don't need this for old ProxyObjects since they were // already initialized. The seqNo of 0 only updates something if it wasn't // set yet. newObj->setLocation(tmv, 0); newObj->setOrientation(tmq, 0); newObj->setBounds(bs, 0); if(meshuri) newObj->setMesh(meshuri, 0); if(phy.size() > 0) newObj->setPhysics(phy, 0); newObj->setIsAggregate(isAggregate, 0); // Notification of the proxy will have already occured, but // updates via, e.g., PositionListener or MeshListener, will go // out here, so the potentially invalid initial data automatically // filled when the object was created by createObject() shouldn't // matter. newObj->setLocation(tmv, seqNo); newObj->setOrientation(tmq, seqNo); newObj->setBounds(bs, seqNo); if(meshuri) newObj->setMesh(meshuri, seqNo); if(phy.size() > 0) newObj->setPhysics(phy, seqNo); newObj->setIsAggregate(isAggregate, seqNo); // Notification has to happen either way notify(&ProxyCreationListener::onCreateProxy, newObj); return newObj; }
void ObjectHost::handleObjectConnected(const SpaceObjectReference& sporef_objid, ServerID server) { ObjectNodeSessionProvider::notify(&ObjectNodeSessionListener::onObjectNodeSession, sporef_objid.space(), sporef_objid.object(), OHDP::NodeID(server)); }
void ObjectHost::handleObjectMigrated(const SpaceObjectReference& sporef_objid, ServerID from, ServerID to) { ObjectNodeSessionProvider::notify(&ObjectNodeSessionListener::onObjectNodeSession, sporef_objid.space(), sporef_objid.object(), OHDP::NodeID(to)); }
void PerPresenceData::populateSpaceObjRef(const SpaceObjectReference& sporef) { validSpaceObjRef = true; space = sporef.space(); object = sporef.object(); }
void HostedObject::processLocationUpdate(const SpaceObjectReference& sporef, ProxyObjectPtr proxy_obj, const LocUpdate& update) { TimedMotionVector3f loc; TimedMotionQuaternion orient; BoundingSphere3f bounds; String mesh; String phy; TimedMotionVector3f* locptr = NULL; uint64 location_seqno = update.location_seqno(); TimedMotionQuaternion* orientptr = NULL; uint64 orient_seqno = update.orientation_seqno(); BoundingSphere3f* boundsptr = NULL; uint64 bounds_seqno = update.bounds_seqno(); String* meshptr = NULL; uint64 mesh_seqno = update.mesh_seqno(); String* phyptr = NULL; uint64 phy_seqno = update.physics_seqno(); if (update.has_epoch()) { // Check if this object is our own presence and update our epoch info if // it is. Mutex::scoped_lock locker(presenceDataMutex); PresenceDataMap::iterator pres_it = mPresenceData.find(sporef); if (pres_it != mPresenceData.end()) { PerPresenceData* pd = pres_it->second; pd->latestReportedEpoch = std::max(pd->latestReportedEpoch, update.epoch()); } } if (update.has_location()) { loc = update.locationWithLocalTime(this, sporef.space()); CONTEXT_OHTRACE(objectLoc, sporef.object().getAsUUID(), //getUUID(), update.object().getAsUUID(), loc ); locptr = &loc; } if (update.has_orientation()) { orient = update.orientationWithLocalTime(this, sporef.space()); orientptr = &orient; } if (update.has_bounds()) { bounds = update.bounds(); boundsptr = &bounds; } if (update.has_mesh()) { mesh = update.mesh(); meshptr = &mesh; } if (update.has_physics()) { phy = update.physics(); phyptr = &phy; } processLocationUpdate( sporef.space(), proxy_obj, false, locptr, location_seqno, orientptr, orient_seqno, boundsptr, bounds_seqno, meshptr, mesh_seqno, phyptr, phy_seqno ); }
std::string CameraEntity::ogreCameraName(const SpaceObjectReference&ref) { return "Camera:"+ref.toString(); }
size_t operator() (const SpaceObjectReference&uuid) const { return uuid.hash(); }
void ObjectHost::handleObjectDisconnected(const SpaceObjectReference& sporef_objid, Disconnect::Code) { ObjectNodeSessionProvider::notify(&ObjectNodeSessionListener::onObjectNodeSession, sporef_objid.space(), sporef_objid.object(), OHDP::NodeID::null()); }
ProxyManagerPtr HostedObject::presence(const SpaceObjectReference& sor) { return getProxyManager(sor.space(), sor.object()); }
void ObjectHost::registerHostedObject(const SpaceObjectReference &sporef_uuid, const HostedObjectPtr& obj) { HostedObjectMap::iterator iter = mHostedObjects.find(sporef_uuid); if (iter != mHostedObjects.end()) { SILOG(oh,error,"Two objects having the same internal name in the mHostedObjects map on connect"<<sporef_uuid.toString()); } mHostedObjects[sporef_uuid]=obj; }
void HostedObject::handleProximityUpdate(const SpaceObjectReference& spaceobj, const Sirikata::Protocol::Prox::ProximityUpdate& update) { HostedObject* self = this; SpaceID space = spaceobj.space(); ProxyManagerPtr proxy_manager = self->getProxyManager(spaceobj.space(),spaceobj.object()); if (!proxy_manager) { HO_LOG(warn,"Hosted Object received a message for a presence without a proxy manager."); return; } for(int32 aidx = 0; aidx < update.addition_size(); aidx++) { Sirikata::Protocol::Prox::ObjectAddition addition = update.addition(aidx); ProxProtocolLocUpdate add(addition); SpaceObjectReference proximateID(spaceobj.space(), add.object()); TimedMotionVector3f loc(add.locationWithLocalTime(this, spaceobj.space())); CONTEXT_OHTRACE(prox, spaceobj.object().getAsUUID(), //getUUID(), addition.object(), true, loc ); TimedMotionQuaternion orient(add.orientationWithLocalTime(this, spaceobj.space())); BoundingSphere3f bnds = add.bounds(); String mesh = add.meshOrDefault(); String phy = add.physicsOrDefault(); bool isAggregate = (addition.type() == Sirikata::Protocol::Prox::ObjectAddition::Aggregate) ? true : false; ProxyObjectPtr proxy_obj = proxy_manager->getProxyObject(proximateID); if (!proxy_obj) { Transfer::URI meshuri; if (addition.has_mesh()) meshuri = Transfer::URI(addition.mesh()); // FIXME use weak_ptr instead of raw uint64 proxyAddSeqNo = add.location_seqno(); assert( add.location_seqno() == add.orientation_seqno() && add.location_seqno() == add.bounds_seqno() && add.location_seqno() == add.mesh_seqno() && add.location_seqno() == add.physics_seqno()); proxy_obj = self->createProxy(proximateID, spaceobj, meshuri, loc, orient, bnds, phy, "", isAggregate, proxyAddSeqNo); } else { // We need to handle optional values properly -- they // shouldn't get overwritten. String* mesh_ptr = (addition.has_mesh() ? &mesh : NULL); String* phy_ptr = (addition.has_physics() ? &phy : NULL); self->processLocationUpdate(space, proxy_obj, false, &loc, add.location_seqno(), &orient, add.orientation_seqno(), &bnds, add.bounds_seqno(), mesh_ptr, add.mesh_seqno(), phy_ptr, add.physics_seqno() ); } // Always mark the object as valid (either revalidated, or just // valid for the first time) if (proxy_obj) proxy_obj->validate(); //tells the object script that something that was close has come //into view if(self->mObjectScript) self->mObjectScript->notifyProximate(proxy_obj,spaceobj); } for(int32 ridx = 0; ridx < update.removal_size(); ridx++) { Sirikata::Protocol::Prox::ObjectRemoval removal = update.removal(ridx); SpaceObjectReference removed_obj_ref(spaceobj.space(), ObjectReference(removal.object())); bool permanent = (removal.has_type() && (removal.type() == Sirikata::Protocol::Prox::ObjectRemoval::Permanent)); if (removed_obj_ref == spaceobj) { // We want to ignore removal of ourself -- we should // always be in our result set, and we don't want to // delete our own proxy. SILOG(oh,detailed,"Ignoring self removal from proximity results."); } else { ProxyObjectPtr proxy_obj = proxy_manager->getProxyObject(removed_obj_ref); if (proxy_obj) { // NOTE: We *don't* reset the proxy object // here. Resetting it puts the seqnos back at 0, // but if we get an addition while still on this // space server, we actually want the old ones to // stay in place, in case of unordered prox/loc // updates. Resetting only happens when we move // across space servers (see handleMigrated). proxy_manager->destroyObject(proxy_obj); if (self->mObjectScript) self->mObjectScript->notifyProximateGone(proxy_obj,spaceobj); proxy_obj->invalidate(permanent); } } CONTEXT_OHTRACE(prox, spaceobj.object().getAsUUID(), //getUUID(), removal.object(), false, TimedMotionVector3f() ); } }
void ObjectHost::unregisterHostedObject(const SpaceObjectReference& sporef_uuid, HostedObject* key_obj) { HostedObjectMap::iterator iter = mHostedObjects.find(sporef_uuid); if (iter != mHostedObjects.end()) { HostedObjectPtr obj (iter->second); // The NULL case covers the possibility that the connection finishes // after the HostedObject requests destruction and stops paying // attention to connection events if (key_obj == NULL || obj.get()==key_obj) mHostedObjects.erase(iter); else SILOG(oh,error,"Two objects having the same internal name in the mHostedObjects map on disconnect "<<sporef_uuid.toString()); } }
void ManualObjectQueryProcessor::unregisterObjectQuery(const SpaceObjectReference& sporef) { // Get query info ObjectStateMap::iterator it = mObjectState.find(sporef); assert(it != mObjectState.end()); ObjectState& state = it->second; HostedObjectPtr ho = state.who.lock(); // unregisterObjectQuery can happen due to disconnection where we // want to preserve the query info, so we can't assert an empty // query like we assert a non-empty one in registerOrUpdateObjectQuery assert( ho && state.node != OHDP::NodeID::null() ); // Get the appropriate handler QueryHandlerMap::iterator handler_it = mObjectQueryHandlers.find(OHDP::SpaceNodeID(sporef.space(), state.node)); assert(handler_it != mObjectQueryHandlers.end()); ObjectQueryHandlerPtr handler = handler_it->second; // And unregister handler->removeQuery(ho, sporef); state.registered = false; }
Endpoint::Endpoint(const SpaceObjectReference& space_obj, const PortID& port) : mSpace(space_obj.space()), mObject(space_obj.object()), mPort(port) { }
bool operator==(const SpaceObjectReference& rhs) const { return space()==rhs.space()&&object()==rhs.object(); }
bool operator<(const SpaceObjectReference& rhs) const { if (space()==rhs.space()) return object()<rhs.object(); return space()<rhs.space(); }
ODPSST::Stream::Ptr HostedObject::getSpaceStream(const SpaceObjectReference& sor) { return mObjectHost->getSpaceStream(sor.space(), sor.object()); }