Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/_docs/events/listening-to-events.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ include::code-snippets/dotnet/WorkingWithEvents.cs[tag=enablingEvents,indent=0]
tab:C++[unsupported]
--

Events can also be enabled/disabled in runtime by the link:tools/control-script[control utility].

== Getting the Events Interface

The events functionality is available through the events interface, which provides methods for listening to cluster events. The events interface can be obtained from an instance of `Ignite` as follows:
Expand Down
15 changes: 15 additions & 0 deletions docs/_docs/tools/control-script.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1628,3 +1628,18 @@ Parameters:
|--node-id | A list of nodes to rebuild indexes on. If not specified, schedules rebuild on all nodes.
|--cache-names | Comma-separated list of cache names, optionally with indexes. If indexes are not specified, all indexes of the cache will be scheduled for the rebuild operation. Can be used simultaneously with cache group names.
|--group-names | Comma-separated list of cache group names. Can be used simultaneously with cache names.


== Events subscription management

By default, almost all link:events/events[Ignite events] are disabled (except for a few that are implicitly enabled because they are required by the system).
To use event listeners, you must explicitly enable each event type you're interested in. This can be done either statically via `IgniteConfiguration` (as described in the link:events/listening-to-events[Working with Events] section), or dynamically during runtime using the control utility.
The control utility provides commands to enable events, disable events, check the status of enabled events and get a list of supported by the Ignite events.

[source, shell]
----
control.sh|bat --event enable event1[,...,eventN]
control.sh|bat --event disable event1[,...,eventN]
control.sh|bat --event status
control.sh|bat --event list
----
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.apache.ignite.util.GridCommandHandlerConsistencySensitiveTest;
import org.apache.ignite.util.GridCommandHandlerConsistencyTest;
import org.apache.ignite.util.GridCommandHandlerDefragmentationTest;
import org.apache.ignite.util.GridCommandHandlerEventTest;
import org.apache.ignite.util.GridCommandHandlerIndexForceRebuildTest;
import org.apache.ignite.util.GridCommandHandlerIndexListTest;
import org.apache.ignite.util.GridCommandHandlerIndexRebuildStatusTest;
Expand Down Expand Up @@ -64,6 +65,8 @@
GridCommandHandlerConsistencySensitiveTest.class,
GridCommandHandlerConsistencyRepairCorrectnessAtomicTest.class,

GridCommandHandlerEventTest.class,

RollingUpgradeCommandTest.class,
SystemViewCommandTest.class,
MetricCommandTest.class,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.ignite.util;

import java.security.Permissions;
import org.apache.ignite.Ignite;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.events.EventType;
import org.apache.ignite.internal.processors.security.impl.TestSecurityData;
import org.apache.ignite.internal.processors.security.impl.TestSecurityPluginProvider;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.G;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.junit.Test;

import static org.apache.ignite.internal.commandline.CommandHandler.EXIT_CODE_OK;
import static org.apache.ignite.internal.commandline.CommandHandler.EXIT_CODE_UNEXPECTED_ERROR;
import static org.apache.ignite.internal.commandline.SecurityCommandHandlerPermissionsTest.DEFAULT_PWD;
import static org.apache.ignite.internal.commandline.SecurityCommandHandlerPermissionsTest.TEST_NO_PERMISSIONS_LOGIN;
import static org.apache.ignite.internal.commandline.SecurityCommandHandlerPermissionsTest.enrichWithConnectionArguments;
import static org.apache.ignite.plugin.security.SecurityPermission.ADMIN_OPS;
import static org.apache.ignite.plugin.security.SecurityPermission.EVENTS_DISABLE;
import static org.apache.ignite.plugin.security.SecurityPermission.EVENTS_ENABLE;
import static org.apache.ignite.plugin.security.SecurityPermissionSetBuilder.ALL_PERMISSIONS;
import static org.apache.ignite.plugin.security.SecurityPermissionSetBuilder.NO_PERMISSIONS;
import static org.apache.ignite.plugin.security.SecurityPermissionSetBuilder.systemPermissions;
import static org.junit.Assume.assumeTrue;

/** */
public class GridCommandHandlerEventTest extends GridCommandHandlerAbstractTest {
/** */
private static final String LOGIN_EVT_ENABLE = "test_login_evt_enable";

/** */
private static final String LOGIN_EVT_DISABLE = "test_login_evt_disable";

/** */
private static final String LOGIN_EVT_STATUS = "test_login_evt_status";

/** */
@Override protected void afterTest() throws Exception {
super.afterTest();

stopAllGrids();
}

/** */
@Test
public void testEventEnableDIsable() throws Exception {
startGrids(2);
startClientGrid("client");

assertEvents(false, EventType.EVT_CACHE_STARTED, EventType.EVT_CACHE_STOPPED);

assertEquals(EXIT_CODE_OK, execute("--event", "enable", "EVT_CACHE_STARTED,EVT_CACHE_STOPPED"));

assertEvents(true, EventType.EVT_CACHE_STARTED, EventType.EVT_CACHE_STOPPED);

injectTestSystemOut();

assertEquals(EXIT_CODE_OK, execute("--event", "status"));

String out = testOut.toString();

assertTrue(out.contains("EVT_CACHE_STARTED"));
assertTrue(out.contains("EVT_CACHE_STOPPED"));

assertEquals(EXIT_CODE_OK, execute("--event", "disable", "EVT_CACHE_STARTED,EVT_CACHE_STOPPED"));

assertEvents(false, EventType.EVT_CACHE_STARTED, EventType.EVT_CACHE_STOPPED);
}

/** */
@Test
public void testDifferentSetOfEventsOnNodes() throws Exception {
startGrid(getConfiguration(getTestIgniteInstanceName(0))
.setIncludeEventTypes(EventType.EVT_TX_STARTED, EventType.EVT_CACHE_STARTED));

startGrid(getConfiguration(getTestIgniteInstanceName(1))
.setIncludeEventTypes(EventType.EVT_TX_STARTED, EventType.EVT_CACHE_STOPPED));

injectTestSystemOut();

assertEquals(EXIT_CODE_OK, execute("--event", "status"));

String out = testOut.toString();

assertTrue(out.contains("EVT_TX_STARTED"));
assertTrue(out.contains("Warning: Event EVT_CACHE_STARTED is enabled only on part of nodes"));
assertTrue(out.contains("Warning: Event EVT_CACHE_STOPPED is enabled only on part of nodes"));
}

/** */
@Test
public void testUnknownEvent() throws Exception {
startGrids(2);

assertEquals(EXIT_CODE_UNEXPECTED_ERROR, execute("--event", "enable", "EVT_NO_SUCH_EVENT"));
}

/** */
@Test
public void testEventList() throws Exception {
startGrids(2);

injectTestSystemOut();

assertEquals(EXIT_CODE_OK, execute("--event", "list"));

String out = testOut.toString();

for (String evt : U.gridEventNames().values())
assertTrue(out.contains("EVT_" + evt));
}

/** */
@Test
public void testEventWithSecurity() throws Exception {
assumeTrue(cliCommandHandler());

startGrid(getConfigurationWithSecurity(getTestIgniteInstanceName(0)));
startGrid(getConfigurationWithSecurity(getTestIgniteInstanceName(1)));

assertExecuteWithSecurity(LOGIN_EVT_ENABLE, "--event", "enable", "EVT_CACHE_STARTED,EVT_CACHE_STOPPED");

assertEvents(true, EventType.EVT_CACHE_STARTED, EventType.EVT_CACHE_STOPPED);

assertExecuteWithSecurity(LOGIN_EVT_STATUS, "--event", "status");

assertExecuteWithSecurity(LOGIN_EVT_DISABLE, "--event", "disable", "EVT_CACHE_STARTED,EVT_CACHE_STOPPED");

assertEvents(false, EventType.EVT_CACHE_STARTED, EventType.EVT_CACHE_STOPPED);
}

/** */
private IgniteConfiguration getConfigurationWithSecurity(String igniteInstanceName) throws Exception {
IgniteConfiguration cfg = getConfiguration(igniteInstanceName);

cfg.setPluginProviders(
new TestSecurityPluginProvider(
igniteInstanceName,
DEFAULT_PWD,
ALL_PERMISSIONS,
false,
new TestSecurityData(TEST_NO_PERMISSIONS_LOGIN, DEFAULT_PWD, NO_PERMISSIONS, new Permissions()),
new TestSecurityData(LOGIN_EVT_ENABLE, DEFAULT_PWD, systemPermissions(EVENTS_ENABLE), new Permissions()),
new TestSecurityData(LOGIN_EVT_DISABLE, DEFAULT_PWD, systemPermissions(EVENTS_DISABLE), new Permissions()),
new TestSecurityData(LOGIN_EVT_STATUS, DEFAULT_PWD, systemPermissions(ADMIN_OPS), new Permissions()))
);

return cfg;
}

/** */
private void assertExecuteWithSecurity(String allowedLogin, String... cmdArgs) {
assertEquals(EXIT_CODE_UNEXPECTED_ERROR, execute(enrichWithConnectionArguments(F.asList(cmdArgs),
TEST_NO_PERMISSIONS_LOGIN)));

assertEquals(EXIT_CODE_OK, execute(enrichWithConnectionArguments(F.asList(cmdArgs), allowedLogin)));
}

/** */
private void assertEvents(boolean enabled, int... evts) {
for (Ignite ignite : G.allGrids()) {
for (int i = 0; i < evts.length; i++)
assertEquals(enabled, ignite.events().isEnabled(evts[i]));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.apache.ignite.internal.management.defragmentation.DefragmentationCommand;
import org.apache.ignite.internal.management.diagnostic.DiagnosticCommand;
import org.apache.ignite.internal.management.encryption.EncryptionCommand;
import org.apache.ignite.internal.management.event.EventCommand;
import org.apache.ignite.internal.management.kill.KillCommand;
import org.apache.ignite.internal.management.meta.MetaCommand;
import org.apache.ignite.internal.management.metric.MetricCommand;
Expand Down Expand Up @@ -77,7 +78,8 @@ public IgniteCommandRegistry() {
new DefragmentationCommand(),
new PerformanceStatisticsCommand(),
new CdcCommand(),
new ConsistencyCommand()
new ConsistencyCommand(),
new EventCommand()
);

U.loadService(CommandsProvider.class).forEach(p -> p.commands().forEach(this::register));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.ignite.internal.management.event;

import org.apache.ignite.internal.management.api.CommandRegistryImpl;

/** Command to enable/disable events. */
public class EventCommand extends CommandRegistryImpl {
/** */
public EventCommand() {
super(
new EventEnableCommand(),
new EventDisableCommand(),
new EventStatusCommand(),
new EventListCommand()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.ignite.internal.management.event;

import org.apache.ignite.internal.Order;
import org.apache.ignite.internal.dto.IgniteDataTransferObject;
import org.apache.ignite.internal.management.api.Argument;
import org.apache.ignite.internal.management.api.Positional;

/** */
public class EventCommandArg extends IgniteDataTransferObject {
/** */
private static final long serialVersionUID = 0;

/** */
@Order(0)
@Positional
@Argument(
description = "Comma separated list of events",
example = "event1[,...,eventN]")
String[] events;

/** */
public String[] events() {
return events;
}

/** */
public void events(String[] events) {
this.events = events;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.ignite.internal.management.event;

import java.util.Collection;
import java.util.function.Consumer;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.internal.management.api.ComputeCommand;

/** */
public class EventDisableCommand implements ComputeCommand<EventCommandArg, String> {
/** {@inheritDoc} */
@Override public String description() {
return "Disable events";
}

/** {@inheritDoc} */
@Override public Class<EventDisableCommandArg> argClass() {
return EventDisableCommandArg.class;
}

/** {@inheritDoc} */
@Override public Class<EventEnableDisableTask> taskClass() {
return EventEnableDisableTask.class;
}

/** {@inheritDoc} */
@Override public Collection<ClusterNode> nodes(Collection<ClusterNode> nodes, EventCommandArg arg) {
return nodes;
}

/** {@inheritDoc} */
@Override public void printResult(EventCommandArg arg, String res, Consumer<String> printer) {
printer.accept(res);
}

/** */
public static class EventDisableCommandArg extends EventCommandArg {
/** */
private static final long serialVersionUID = 0;
}
}
Loading
Loading