void PushService::merge( PushService* other, PacketContainerList& packetList, vector<uint32>& lastUpdateTime ) { if ( other->getServiceID() == getServiceID() ) { // Merge resource IDs PushResourceDataMap::iterator it = other->m_resourceData.begin(); while ( it != other->m_resourceData.end() ) { // Find resouceID PushResourceDataMap::iterator fit = m_resourceData.find( it->first ); if ( fit == m_resourceData.end() ) { // Not found packetList.push_back( makeSubscribePacket( *it->first, it->second->getTimeForLastUpdate() ) ); addResource( *it->first, it->second->getTimeForLastUpdate() ); lastUpdateTime.push_back( it->second->getTimeForLastUpdate() ); } else { lastUpdateTime.push_back( fit->second->getTimeForLastUpdate() ); } ++it; } } else { mc2log << warn << "PushService::merge serviceID missmatch! other " << other->getServiceID() << " != " << getServiceID() << endl; } }
uint32 PushService::checkAndCalculateTimeout( PacketContainerList& packetList ) { uint32 now = TimeUtility::getRealTime(); PushResourceDataMap::iterator it = m_resourceData.begin(); uint32 timeNextTimeOut = now + getResendSubscriptionTimeout() + getReceiveTimeout(); // Larger than all timeouts uint32 timeOutTime = 0; while ( it != m_resourceData.end() ) { if ( it->second->getPushSocket() != NULL ) { // Connected timeOutTime = it->second->getTimeForLastProviderContact() + getReceiveTimeout(); if ( timeOutTime <= now ) { mc2dbg2 << "PushService::checkAndCalculateTimeout " << "Connected Resource time out, resubscribe serviceID " << getServiceID() << " resource "; #ifdef DEBUG_LEVEL_2 *it->first << mc2log; #endif mc2dbg2 << " lastUpdateTime " << it->second->getTimeForLastUpdate() << endl; // Timeout, resubscribe it->second->setPushSocket( NULL ); packetList.push_back( makeSubscribePacket( *it->first, it->second->getTimeForLastUpdate() ) ); it->second->setTimeForLastSentSubscription( now ); timeOutTime = it->second->getTimeForLastSentSubscription() + getResendSubscriptionTimeout(); } } else { // Subscribing timeOutTime = it->second->getTimeForLastSentSubscription() + getResendSubscriptionTimeout(); if ( timeOutTime <= now ) { mc2dbg2 << "PushService::checkAndCalculateTimeout " << "Subscribing Resource time out, subscribe serviceID " << getServiceID() << " resource "; #ifdef DEBUG_LEVEL_2 *it->first << mc2log; #endif mc2dbg2 << " lastUpdateTime " << it->second->getTimeForLastUpdate() << endl; // (Re)send subscription it->second->setPushSocket( NULL ); packetList.push_back( makeSubscribePacket( *it->first, it->second->getTimeForLastUpdate() ) ); it->second->setTimeForLastSentSubscription( now ); timeOutTime = it->second->getTimeForLastSentSubscription() + getResendSubscriptionTimeout(); } } if ( timeOutTime < timeNextTimeOut ) { timeNextTimeOut = timeOutTime; } ++it; } return timeNextTimeOut; }
bool Service::finishLoad() { setStatus(SS_WORKING); if (!isShell()) { if (true) { LoadServiceNotice notice; notice.shellServiceInfos.push_back(ServiceInfo( getServiceDockerID(), getServiceType(), getServiceID(), getServiceName(), getStatus(), getClientDockerID(), getClientSessionID())); Docker::getRef().broadcastToDockers(notice, false); } if (getServiceTrait(getServiceType()) == STrait_Multi) { RefreshServiceToMgrNotice refreshNotice; refreshNotice.shellServiceInfos.push_back(ServiceInfo( getServiceDockerID(), getServiceType(), getServiceID(), getServiceName(), getStatus(), getClientDockerID(), getClientSessionID())); for (auto sd : ServiceDepends) { if (getServiceTrait(sd.first) == STrait_Single ) { toService(sd.first, refreshNotice, nullptr); } } } LOGI(*this << "local service finish load. service=" << getServiceName() << ", id=" << getServiceID()); } else { LOGI(*this << "remote service finish load. service=" << getServiceName() << ", id=" << getServiceID()); } return true; }
void Service::toService(ServiceType serviceType, ServiceID serviceID, const OutOfBand &oob, const char * block, unsigned int len, ServiceCallback cb) { Tracing trace; trace.routing.fromServiceType = getServiceType(); trace.routing.fromServiceID = getServiceID(); trace.routing.traceBackID = 0; trace.routing.traceID = 0; trace.routing.toServiceType = serviceType; trace.routing.toServiceID = serviceID; trace.oob = oob; if (cb) { trace.routing.traceID = makeCallback(cb); } if (trace.routing.toServiceType == STClient && trace.routing.toServiceID == InvalidServiceID) { if ((trace.oob.clientDockerID == InvalidDockerID && trace.oob.clientSessionID != InvalidSessionID) || (trace.oob.clientDockerID != InvalidDockerID && trace.oob.clientSessionID == InvalidSessionID)) { LOGE("toService STClient via session ID but param had some wrong. the condition is clientDockerID and clientSessionID need all valid. trace=" << trace); return; } if (trace.oob.clientDockerID == InvalidDockerID && trace.oob.clientAvatarID == InvalidAvatarID && getServiceType() != STAvatar) { LOGE("toService STClient but can not get the avatar ID. trace=" << trace << ", this service=" << getServiceType()); return; } if (trace.oob.clientDockerID == InvalidDockerID && trace.oob.clientAvatarID == InvalidAvatarID && getServiceType() == STAvatar) { trace.routing.toServiceID = getServiceID(); } if (trace.oob.clientDockerID == InvalidDockerID && trace.oob.clientAvatarID != InvalidAvatarID) { trace.routing.toServiceID = trace.oob.clientAvatarID; } } else if (::getServiceTrait(trace.routing.toServiceType) == STrait_Multi && trace.routing.toServiceID == InvalidServiceID) { LOGE("toService STrait_Multi but can not get the toServiceID. trace=" << trace << ", this service=" << getServiceType()); return; } Docker::getRef().toService(trace, block, len, false); }
void Service::toDocker(DockerID dockerID, const char * block, unsigned int len) { OutOfBand oob; if (getServiceType() == STAvatar) { oob.clientDockerID = getClientDockerID(); oob.clientSessionID = getClientSessionID(); oob.clientAvatarID = getServiceID(); } toDocker(dockerID, oob, block, len); }
void Service::toService(ServiceType serviceType, const char * block, unsigned int len, ServiceCallback cb) { OutOfBand oob; if (getServiceType() == STAvatar) { oob.clientDockerID = getClientDockerID(); oob.clientSessionID = getClientSessionID(); oob.clientAvatarID = getServiceID(); } toService(serviceType, InvalidServiceID, oob, block, len, cb); }
bool PushService::handlePushPacket( PushPacket* pushPacket, TCPSocket* pushSocket, PacketContainerList& packetList, bool& isDataPacket, SubscriptionResource*& resource ) { set<SubscriptionResourceNotice> subscribed; set<SubscriptionResourceNotice> unsubscribed; bool isHeartBeat = false; if ( getPushPacketMaps( pushPacket, subscribed, unsubscribed, isHeartBeat ) ) { uint32 now = TimeUtility::getRealTime(); if ( !isHeartBeat && subscribed.begin() != subscribed.end() ) { isDataPacket = true; resource = (**subscribed.begin()).clone(); } set<SubscriptionResourceNotice>::iterator it = subscribed.begin(); while( it != subscribed.end() ) { PushResourceDataMap::iterator rit = m_resourceData.find( *it ); if ( rit == m_resourceData.end() ) { // We don't want this resource to be subscribed mc2dbg2 << "PushService::handlePushPacket, unwanted service " << "unsubscribe, serviceID " << getServiceID() << " resource "; #ifdef DEBUG_LEVEL_2 **it << mc2log; #endif mc2dbg2 << endl; packetList.push_back( makeUnSubscribePacket( **it ) ); } else { // Else all ok subscribed resource found update times rit->second->setPushSocket( pushSocket ); if ( isHeartBeat ) { rit->second->setTimeForLastHeartbeat( now ); } else { // Data packet rit->second->setTimeForLastUpdate( now ); } } ++it; } } else { mc2log << warn << "PushService::handlePushPacket getPushPacketMaps " << "falied, strange packet: " << endl; pushPacket->dump(); } return true; }
bool Service::finishUnload() { setStatus(SS_DESTROY); if (!isShell()) { if (getServiceTrait(getServiceType()) == STrait_Multi) { RefreshServiceToMgrNotice refreshNotice; refreshNotice.shellServiceInfos.push_back(ServiceInfo( getServiceDockerID(), getServiceType(), getServiceID(), getServiceName(), getStatus(), getClientDockerID(), getClientSessionID())); for (auto sd : ServiceDepends) { if (getServiceTrait(sd.first) == STrait_Single) { toService(sd.first, refreshNotice, nullptr); } } } UnloadedServiceNotice notice(getServiceType(), getServiceID()); Docker::getRef().broadcastToDockers(notice, true); LOGI(*this << "local service finish unload. service=" << getServiceName() << ", id=" << getServiceID()); } else { LOGI(*this << "remote service finish unload. service=" << getServiceName() << ", id=" << getServiceID()); } for (auto tID : _repeatTimers) { SessionManager::getRef().cancelTimer(tID); } _repeatTimers.clear(); return true; }
void Service::toDocker(DockerID dockerID, const OutOfBand & oob, const char * block, unsigned int len) { Tracing trc; trc.routing.fromServiceType = getServiceType(); trc.routing.fromServiceID = getServiceID(); trc.routing.traceID = 0; trc.routing.traceBackID = 0; trc.routing.toServiceType = STClient; trc.routing.toServiceID = InvalidServiceID; trc.oob = oob; WriteStream ws(ForwardToDocker::getProtoID()); ws << trc; ws.appendOriginalData(block, len); Docker::getRef().sendViaDockerID(dockerID, ws.getStream(), ws.getStreamLen()); }
void Service::backToService(const Tracing & trace, const char * block, unsigned int len, ServiceCallback cb) { Tracing trc; trc.routing.fromServiceType = getServiceType(); trc.routing.fromServiceID = getServiceID(); trc.routing.traceID = 0; trc.routing.traceBackID = trace.routing.traceID; trc.routing.toServiceType = trace.routing.fromServiceType; trc.routing.toServiceID = trace.routing.fromServiceID; trc.oob = trace.oob; if (cb) { trc.routing.traceID = makeCallback(cb); } Docker::getRef().toService(trc, block, len, false); }
void Service::directToRealClient(DockerID clientDockerID, SessionID clientSessionID, const char * block, unsigned int len) { if (clientDockerID == ServerConfig::getRef().getDockerID()) { Docker::getRef().sendViaSessionID(clientSessionID, block, len); return; } Tracing trc; trc.routing.fromServiceType = getServiceType(); trc.routing.fromServiceID = getServiceID(); trc.routing.traceID = 0; trc.routing.traceBackID = 0; trc.routing.toServiceType = STClient; trc.routing.toServiceID = InvalidServiceID; trc.oob.clientDockerID = clientDockerID; trc.oob.clientSessionID = clientSessionID; trc.oob.clientAvatarID = InvalidServiceID; Docker::getRef().forwardToRemoteService(trc, block, len); }