}
}
-
-void ApiListener::SyncRelayMessage(const MessageOrigin::Ptr& origin,
- const ConfigObject::Ptr& secobj, const Dictionary::Ptr& message, bool log)
+bool ApiListener::RelayMessageOne(const Zone::Ptr& targetZone, const MessageOrigin::Ptr& origin, const Dictionary::Ptr& message)
{
- double ts = Utility::GetTime();
- message->Set("ts", ts);
-
- Log(LogNotice, "ApiListener")
- << "Relaying '" << message->Get("method") << "' message";
-
- if (origin && origin->FromZone)
- message->Set("originZone", origin->FromZone->GetName());
+ ASSERT(targetZone);
bool is_master = IsMaster();
Endpoint::Ptr master = GetMaster();
- Zone::Ptr my_zone = Zone::GetLocalZone();
+ Zone::Ptr myZone = Zone::GetLocalZone();
+
+ /* only relay the message to a) the same zone, b) the parent zone and c) direct child zones */
+ if (targetZone != myZone && targetZone != myZone->GetParent() && targetZone->GetParent() != myZone)
+ return true;
std::vector<Endpoint::Ptr> skippedEndpoints;
- std::set<Zone::Ptr> allZones;
- std::set<Zone::Ptr> finishedZones;
- std::set<Zone::Ptr> finishedLogZones;
- BOOST_FOREACH(const Endpoint::Ptr& endpoint, ConfigType::GetObjectsByType<Endpoint>()) {
+ bool relayed = false, log_needed = false, log_done = false;
+
+ BOOST_FOREACH(const Endpoint::Ptr& endpoint, targetZone->GetEndpoints()) {
/* don't relay messages to ourselves */
if (endpoint == GetLocalEndpoint())
continue;
- Zone::Ptr target_zone = endpoint->GetZone();
-
-
- /* only relay messages to zones which have access to the object */
- if (!target_zone->CanAccessObject(secobj))
- continue;
-
- allZones.insert(target_zone);
+ log_needed = true;
/* don't relay messages to disconnected endpoints */
if (!endpoint->GetConnected()) {
- if (target_zone == my_zone)
- finishedLogZones.erase(target_zone);
+ if (targetZone == myZone)
+ log_done = false;
continue;
}
- finishedLogZones.insert(target_zone);
+ log_done = true;
/* don't relay the message to the zone through more than one endpoint unless this is our own zone */
- if (finishedZones.find(target_zone) != finishedZones.end() && target_zone != my_zone) {
+ if (relayed && targetZone != myZone) {
skippedEndpoints.push_back(endpoint);
continue;
}
}
/* don't relay messages back to the zone which we got the message from */
- if (origin && origin->FromZone && target_zone == origin->FromZone) {
+ if (origin && origin->FromZone && targetZone == origin->FromZone) {
skippedEndpoints.push_back(endpoint);
continue;
}
continue;
}
- /* only relay the message to a) the same zone, b) the parent zone and c) direct child zones */
- if (target_zone != my_zone && target_zone != my_zone->GetParent() &&
- secobj->GetZoneName() != target_zone->GetName()) {
- skippedEndpoints.push_back(endpoint);
- continue;
- }
-
- finishedZones.insert(target_zone);
+ relayed = true;
SyncSendMessage(endpoint, message);
}
- if (log && allZones.size() != finishedLogZones.size())
- PersistMessage(message, secobj);
+ if (!skippedEndpoints.empty()) {
+ double ts = message->Get("ts");
+
+ BOOST_FOREACH(const Endpoint::Ptr& endpoint, skippedEndpoints)
+ endpoint->SetLocalLogPosition(ts);
+ }
+
+ return !log_needed || log_done;
+}
- BOOST_FOREACH(const Endpoint::Ptr& endpoint, skippedEndpoints)
- endpoint->SetLocalLogPosition(ts);
+void ApiListener::SyncRelayMessage(const MessageOrigin::Ptr& origin,
+ const ConfigObject::Ptr& secobj, const Dictionary::Ptr& message, bool log)
+{
+ double ts = Utility::GetTime();
+ message->Set("ts", ts);
+
+ Log(LogNotice, "ApiListener")
+ << "Relaying '" << message->Get("method") << "' message";
+
+ if (origin && origin->FromZone)
+ message->Set("originZone", origin->FromZone->GetName());
+
+ Zone::Ptr target_zone;
+
+ if (secobj) {
+ if (secobj->GetReflectionType() == Zone::TypeInstance)
+ target_zone = static_pointer_cast<Zone>(secobj);
+ else
+ target_zone = static_pointer_cast<Zone>(secobj->GetZone());
+ }
+
+ if (!target_zone)
+ target_zone = Zone::GetLocalZone();
+
+ bool need_log = !RelayMessageOne(target_zone, origin, message);
+
+ BOOST_FOREACH(const Zone::Ptr& zone, target_zone->GetAllParents()) {
+ if (!RelayMessageOne(zone, origin, message))
+ need_log = true;
+ }
+
+ if (log && need_log)
+ PersistMessage(message, secobj);
}
String ApiListener::GetApiDir(void)