in modules/configuration/src/main/java/org/apache/ignite/internal/configuration/notifications/ConfigurationNotifier.java [100:343]
private static void notifyListeners(
@Nullable InnerNode oldInnerNode,
InnerNode newInnerNode,
DynamicConfiguration<InnerNode, ?> config,
Iterable<DynamicConfiguration<InnerNode, ?>> anyConfigs,
ConfigurationNotificationContext ctx
) {
assert !(config instanceof NamedListConfiguration);
if (oldInnerNode == null || newInnerNode == oldInnerNode) {
return;
}
notifyPublicListeners(
listeners(config, ctx.notificationNum),
concat(mapIterable(anyConfigs, anyCfg -> listeners(anyCfg, ctx.notificationNum))),
oldInnerNode.specificNode(),
newInnerNode.specificNode(),
ctx,
ConfigurationListener::onUpdate
);
// Polymorphic configuration type has changed.
// At the moment, we do not separate common fields from fields of a specific polymorphic configuration,
// so this may cause errors in the logic below, perhaps we will fix it later.
// TODO: https://issues.apache.org/jira/browse/IGNITE-15916
if (oldInnerNode.schemaType() != newInnerNode.schemaType()) {
return;
}
oldInnerNode.traverseChildren(new ConfigurationVisitor<Void>() {
/** {@inheritDoc} */
@Override
public Void visitLeafNode(Field field, String key, Serializable oldLeaf) {
Serializable newLeaf = newInnerNode.traverseChild(key, leafNodeVisitor(), true);
if (newLeaf != oldLeaf) {
// TODO: Remove null check after https://issues.apache.org/jira/browse/IGNITE-21101
DynamicProperty<Serializable> node = config != null ? dynamicProperty(config, key) : null;
notifyPublicListeners(
listeners(node, ctx.notificationNum),
concat(mapIterable(anyConfigs, anyCfg -> listeners(dynamicProperty(anyCfg, key), ctx.notificationNum))),
oldLeaf,
newLeaf,
ctx,
ConfigurationListener::onUpdate
);
}
return null;
}
/** {@inheritDoc} */
@Override
public Void visitInnerNode(Field field, String key, InnerNode oldNode) {
InnerNode newNode = newInnerNode.traverseChild(key, innerNodeVisitor(), true);
DynamicConfiguration<InnerNode, ?> newConfig = dynamicConfig(config, key);
ctx.addContainer(oldNode, newNode, null, null);
notifyListeners(
oldNode,
newNode,
newConfig,
mapIterable(anyConfigs, anyCfg -> dynamicConfig(anyCfg, key)),
ctx
);
ctx.removeContainer();
return null;
}
/** {@inheritDoc} */
@Override
public Void visitNamedListNode(Field field, String key, NamedListNode<?> oldNamedList) {
NamedListNode<InnerNode> newNamedList =
(NamedListNode<InnerNode>) newInnerNode.traverseChild(key, namedListNodeVisitor(), true);
if (newNamedList != oldNamedList) {
notifyPublicListeners(
listeners(namedDynamicConfig(config, key), ctx.notificationNum),
concat(mapIterable(anyConfigs, anyCfg -> listeners(namedDynamicConfig(anyCfg, key), ctx.notificationNum))),
oldNamedList,
newNamedList,
ctx,
ConfigurationListener::onUpdate
);
NamedListChanges namedListChanges = NamedListChanges.of(oldNamedList, newNamedList);
NamedListConfiguration<?, InnerNode, ?> namedListCfg = namedDynamicConfig(config, key);
Map<String, ConfigurationProperty<?>> namedListCfgMembers = namedListCfg.touchMembers();
// Lazy initialization.
Iterable<DynamicConfiguration<InnerNode, ?>> newAnyConfigs = null;
for (String name : namedListChanges.created) {
DynamicConfiguration<InnerNode, ?> newNodeCfg =
(DynamicConfiguration<InnerNode, ?>) namedListCfg.members().get(name);
touch(newNodeCfg);
InnerNode newVal = newNamedList.getInnerNode(name);
ctx.addContainer(null, newVal, null, name);
notifyPublicListeners(
extendedListeners(namedDynamicConfig(config, key), ctx.notificationNum),
concat(mapIterable(
anyConfigs,
anyCfg -> extendedListeners(namedDynamicConfig(anyCfg, key), ctx.notificationNum)
)),
null,
newVal.specificNode(),
ctx,
ConfigurationNamedListListener::onCreate
);
if (newAnyConfigs == null) {
newAnyConfigs = mergeAnyConfigs(
mapIterable(anyConfigs, anyCfg -> any(namedDynamicConfig(anyCfg, key))),
any(namedListCfg)
);
}
notifyListeners(
newVal,
newNodeCfg,
newAnyConfigs,
ctx
);
ctx.removeContainer();
}
for (String name : namedListChanges.deleted) {
DynamicConfiguration<InnerNode, ?> delNodeCfg =
(DynamicConfiguration<InnerNode, ?>) namedListCfgMembers.get(name);
InnerNode oldVal = oldNamedList.getInnerNode(name);
ctx.addContainer(oldVal, null, name, null);
notifyPublicListeners(
extendedListeners(namedDynamicConfig(config, key), ctx.notificationNum),
concat(mapIterable(
anyConfigs,
anyCfg -> extendedListeners(namedDynamicConfig(anyCfg, key), ctx.notificationNum)
)),
oldVal.specificNode(),
null,
ctx,
ConfigurationNamedListListener::onDelete
);
// Notification for deleted configuration.
notifyPublicListeners(
listeners(delNodeCfg, ctx.notificationNum),
concat(mapIterable(
anyConfigs,
anyCfg -> listeners(any(namedDynamicConfig(anyCfg, key)), ctx.notificationNum)
)),
oldVal.specificNode(),
null,
ctx,
ConfigurationListener::onUpdate
);
ctx.removeContainer();
}
for (Map.Entry<String, String> entry : namedListChanges.renamed.entrySet()) {
InnerNode oldVal = oldNamedList.getInnerNode(entry.getKey());
InnerNode newVal = newNamedList.getInnerNode(entry.getValue());
ctx.addContainer(oldVal, newVal, entry.getKey(), entry.getValue());
notifyPublicListeners(
extendedListeners(namedDynamicConfig(config, key), ctx.notificationNum),
concat(mapIterable(
anyConfigs,
anyCfg -> extendedListeners(namedDynamicConfig(anyCfg, key), ctx.notificationNum)
)),
oldVal.specificNode(),
newVal.specificNode(),
ctx,
(listener, event) -> listener.onRename(event)
);
ctx.removeContainer();
}
for (String name : namedListChanges.updated) {
InnerNode oldVal = oldNamedList.getInnerNode(name);
InnerNode newVal = newNamedList.getInnerNode(name);
if (oldVal == newVal) {
continue;
}
DynamicConfiguration<InnerNode, ?> updNodeCfg =
(DynamicConfiguration<InnerNode, ?>) namedListCfgMembers.get(name);
ctx.addContainer(oldVal, newVal, name, name);
notifyPublicListeners(
extendedListeners(namedDynamicConfig(config, key), ctx.notificationNum),
concat(mapIterable(
anyConfigs,
anyCfg -> extendedListeners(namedDynamicConfig(anyCfg, key), ctx.notificationNum)
)),
oldVal.specificNode(),
newVal.specificNode(),
ctx,
ConfigurationNamedListListener::onUpdate
);
if (newAnyConfigs == null) {
newAnyConfigs = mergeAnyConfigs(
mapIterable(anyConfigs, anyCfg -> any(namedDynamicConfig(anyCfg, key))),
any(namedListCfg)
);
}
notifyListeners(
oldVal,
newVal,
updNodeCfg,
newAnyConfigs,
ctx
);
ctx.removeContainer();
}
}
return null;
}
}, true);
}