DynamicObject::OnTransactionClosing.connect(boost::bind(&ReplicationComponent::TransactionClosingHandler, this, _1));
Endpoint::OnConnected.connect(boost::bind(&ReplicationComponent::EndpointConnectedHandler, this, _1));
-
+
m_Endpoint->RegisterTopicHandler("config::ObjectUpdate",
boost::bind(&ReplicationComponent::RemoteObjectUpdateHandler, this, _3));
m_Endpoint->RegisterTopicHandler("config::ObjectRemoved",
MakeObjectMessage(object, "config::ObjectRemoved", 0, false));
}
-void ReplicationComponent::TransactionClosingHandler(const set<DynamicObject::Ptr>& modifiedObjects)
+void ReplicationComponent::TransactionClosingHandler(const set<DynamicObject *>& modifiedObjects)
{
if (modifiedObjects.empty())
return;
msgbuf << "Sending " << modifiedObjects.size() << " replication updates.";
Logger::Write(LogDebug, "replication", msgbuf.str());
- BOOST_FOREACH(const DynamicObject::Ptr& object, modifiedObjects) {
+ BOOST_FOREACH(DynamicObject *robject, modifiedObjects) {
+ DynamicObject::Ptr object = robject->GetSelf();
+
if (!ShouldReplicateObject(object))
continue;
object = dtype->CreateObject(update);
if (source == EndpointManager::GetInstance()->GetIdentity()) {
- /* the peer sent us an object that was originally created by us -
+ /* the peer sent us an object that was originally created by us -
* however it was deleted locally so we have to tell the peer to destroy
* its copy of the object. */
EndpointManager::GetInstance()->SendMulticastMessage(m_Endpoint,
void LocalObjectRegisteredHandler(const DynamicObject::Ptr& object);
void LocalObjectUnregisteredHandler(const DynamicObject::Ptr& object);
- void TransactionClosingHandler(const set<DynamicObject::Ptr>& modifiedObjects);
+ void TransactionClosingHandler(const set<DynamicObject *>& modifiedObjects);
void RemoteObjectUpdateHandler(const RequestMessage& request);
void RemoteObjectRemovedHandler(const RequestMessage& request);
using namespace icinga;
double DynamicObject::m_CurrentTx = 0;
-set<DynamicObject::Ptr> DynamicObject::m_ModifiedObjects;
+set<DynamicObject *> DynamicObject::m_ModifiedObjects;
boost::signal<void (const DynamicObject::Ptr&)> DynamicObject::OnRegistered;
boost::signal<void (const DynamicObject::Ptr&)> DynamicObject::OnUnregistered;
-boost::signal<void (const set<DynamicObject::Ptr>&)> DynamicObject::OnTransactionClosing;
+boost::signal<void (const set<DynamicObject *>&)> DynamicObject::OnTransactionClosing;
DynamicObject::DynamicObject(const Dictionary::Ptr& serializedObject)
: m_ConfigTx(0)
/* apply config state from the config item/remote update;
* The DynamicObject::Create function takes care of restoring
* non-config state after the object has been fully constructed */
- InternalApplyUpdate(serializedObject, Attribute_Config, true);
+ ApplyUpdate(serializedObject, Attribute_Config);
+}
+
+DynamicObject::~DynamicObject(void)
+{
+ m_ModifiedObjects.erase(this);
+}
+
+void DynamicObject::SendLocalUpdateEvents(void)
+{
+ map<String, Value, string_iless>::iterator it;
+ for (it = m_ModifiedAttributes.begin(); it != m_ModifiedAttributes.end(); it++) {
+ OnAttributeChanged(it->first, it->second);
+ }
+
+ m_ModifiedAttributes.clear();
}
Dictionary::Ptr DynamicObject::BuildUpdate(double sinceTx, int attributeTypes) const
void DynamicObject::ApplyUpdate(const Dictionary::Ptr& serializedUpdate,
int allowedTypes)
-{
- InternalApplyUpdate(serializedUpdate, allowedTypes, false);
-}
-
-void DynamicObject::InternalApplyUpdate(const Dictionary::Ptr& serializedUpdate,
- int allowedTypes, bool suppressEvents)
{
double configTx = 0;
if ((allowedTypes & Attribute_Config) != 0 &&
if (!HasAttribute(it->first))
RegisterAttribute(it->first, static_cast<DynamicAttributeType>(type));
- InternalSetAttribute(it->first, data, tx, suppressEvents, true);
+ InternalSetAttribute(it->first, data, tx, true);
}
}
}
void DynamicObject::InternalSetAttribute(const String& name, const Value& data,
- double tx, bool suppressEvent, bool allowEditConfig)
+ double tx, bool allowEditConfig)
{
DynamicAttribute attr;
attr.Type = Attribute_Transient;
if (tt.first->second.Type & Attribute_Config)
m_ConfigTx = tx;
- if (!suppressEvent) {
- m_ModifiedObjects.insert(GetSelf());
- OnAttributeChanged(name, oldValue);
- }
+ m_ModifiedObjects.insert(this);
+
+ /* Use insert() rather than [] so we don't overwrite
+ * an existing oldValue if the attribute was previously
+ * changed in the same transaction */
+ m_ModifiedAttributes.insert(make_pair(name, oldValue));
}
Value DynamicObject::InternalGetAttribute(const String& name) const
void DynamicObject::FinishTx(void)
{
+ BOOST_FOREACH(DynamicObject *object, m_ModifiedObjects) {
+ object->SendLocalUpdateEvents();
+ }
+
OnTransactionClosing(m_ModifiedObjects);
m_ModifiedObjects.clear();
typedef AttributeMap::const_iterator AttributeConstIterator;
DynamicObject(const Dictionary::Ptr& serializedObject);
+ ~DynamicObject(void);
Dictionary::Ptr BuildUpdate(double sinceTx, int attributeTypes) const;
void ApplyUpdate(const Dictionary::Ptr& serializedUpdate, int allowedTypes);
static boost::signal<void (const DynamicObject::Ptr&)> OnRegistered;
static boost::signal<void (const DynamicObject::Ptr&)> OnUnregistered;
- static boost::signal<void (const set<DynamicObject::Ptr>&)> OnTransactionClosing;
+ static boost::signal<void (const set<DynamicObject *>&)> OnTransactionClosing;
ScriptTask::Ptr InvokeMethod(const String& method,
const vector<Value>& arguments, ScriptTask::CompletionCallback callback);
virtual void OnInitCompleted(void);
private:
- void InternalSetAttribute(const String& name, const Value& data, double tx, bool suppressEvent = false, bool allowEditConfig = false);
+ void InternalSetAttribute(const String& name, const Value& data, double tx, bool allowEditConfig = false);
Value InternalGetAttribute(const String& name) const;
+ void SendLocalUpdateEvents(void);
AttributeMap m_Attributes;
+ map<String, Value, string_iless> m_ModifiedAttributes;
double m_ConfigTx;
static double m_CurrentTx;
- static set<DynamicObject::Ptr> m_ModifiedObjects;
-
- void InternalApplyUpdate(const Dictionary::Ptr& serializedUpdate, int allowedTypes, bool suppressEvents);
+ /* This has to be a set of raw pointers because the DynamicObject
+ * constructor has to be able to insert objects into this list. */
+ static set<DynamicObject *> m_ModifiedObjects;
friend class DynamicType; /* for OnInitCompleted */
};
HostGroup::InvalidateMembersCache();
DowntimeProcessor::InvalidateDowntimeCache();
- Event::Post(boost::bind(&Host::UpdateSlaveServices, this));
+ UpdateSlaveServices();
}
Host::~Host(void)