/* * 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.igfs; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.apache.ignite.Ignite; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteException; import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.configuration.FileSystemConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.events.Event; import org.apache.ignite.events.IgfsEvent; import org.apache.ignite.internal.IgnitionEx; import org.apache.ignite.internal.processors.igfs.IgfsImpl; import org.apache.ignite.internal.util.typedef.P1; import org.apache.ignite.lang.IgnitePredicate; import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi; import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; import org.jetbrains.annotations.Nullable; import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL; import static org.apache.ignite.cache.CacheMode.PARTITIONED; import static org.apache.ignite.cache.CacheMode.REPLICATED; import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC; import static org.apache.ignite.events.EventType.EVTS_IGFS; import static org.apache.ignite.events.EventType.EVT_IGFS_DIR_CREATED; import static org.apache.ignite.events.EventType.EVT_IGFS_DIR_DELETED; import static org.apache.ignite.events.EventType.EVT_IGFS_DIR_RENAMED; import static org.apache.ignite.events.EventType.EVT_IGFS_FILE_CLOSED_READ; import static org.apache.ignite.events.EventType.EVT_IGFS_FILE_CLOSED_WRITE; import static org.apache.ignite.events.EventType.EVT_IGFS_FILE_CREATED; import static org.apache.ignite.events.EventType.EVT_IGFS_FILE_DELETED; import static org.apache.ignite.events.EventType.EVT_IGFS_FILE_OPENED_READ; import static org.apache.ignite.events.EventType.EVT_IGFS_FILE_OPENED_WRITE; import static org.apache.ignite.events.EventType.EVT_IGFS_FILE_PURGED; import static org.apache.ignite.events.EventType.EVT_IGFS_FILE_RENAMED; import static org.apache.ignite.events.EventType.EVT_JOB_MAPPED; import static org.apache.ignite.events.EventType.EVT_TASK_FAILED; import static org.apache.ignite.events.EventType.EVT_TASK_FINISHED; import static org.apache.ignite.testframework.GridTestUtils.assertOneToOne; /** * Tests events, generated by {@link org.apache.ignite.IgniteFileSystem} implementation. */ public abstract class IgfsEventsAbstractSelfTest extends GridCommonAbstractTest { /** IGFS. */ private static IgfsImpl igfs; /** Event listener. */ private IgnitePredicate<Event> lsnr; /** * @return IGFS configuration for this test. */ protected FileSystemConfiguration getIgfsConfiguration() throws IgniteCheckedException { FileSystemConfiguration igfsCfg = new FileSystemConfiguration(); igfsCfg.setName("igfs"); igfsCfg.setBlockSize(512 * 1024); // Together with group blocks mapper will yield 64M per node groups. CacheConfiguration dataCacheCfg = defaultCacheConfiguration(); dataCacheCfg.setCacheMode(PARTITIONED); dataCacheCfg.setNearConfiguration(null); dataCacheCfg.setWriteSynchronizationMode(FULL_SYNC); dataCacheCfg.setEvictionPolicy(null); dataCacheCfg.setAffinityMapper(new IgfsGroupDataBlocksKeyMapper(128)); dataCacheCfg.setBackups(0); dataCacheCfg.setAtomicityMode(TRANSACTIONAL); CacheConfiguration metaCacheCfg = defaultCacheConfiguration(); metaCacheCfg.setCacheMode(REPLICATED); metaCacheCfg.setWriteSynchronizationMode(FULL_SYNC); metaCacheCfg.setEvictionPolicy(null); metaCacheCfg.setAtomicityMode(TRANSACTIONAL); igfsCfg.setMetaCacheConfiguration(metaCacheCfg); igfsCfg.setDataCacheConfiguration(dataCacheCfg); return igfsCfg; } /** {@inheritDoc} */ @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { return getConfiguration(igniteInstanceName, getIgfsConfiguration()); } /** * The same as getConfiguration(String igniteInstanceName) but it sets custom IGFS configuration * * @param igniteInstanceName Ignite instance name. * @param igfsCfg IGFS configuration. * @return Grid configuration. * @throws Exception If failed. */ protected IgniteConfiguration getConfiguration(String igniteInstanceName, FileSystemConfiguration igfsCfg) throws Exception { IgniteConfiguration cfg = IgnitionEx.loadConfiguration("config/hadoop/default-config.xml").get1(); assert cfg != null; cfg.setIgniteInstanceName(igniteInstanceName); cfg.setIncludeEventTypes(concat(EVTS_IGFS, EVT_TASK_FAILED, EVT_TASK_FINISHED, EVT_JOB_MAPPED)); cfg.setFileSystemConfiguration(igfsCfg); cfg.setHadoopConfiguration(null); TcpDiscoverySpi discoSpi = new TcpDiscoverySpi(); discoSpi.setIpFinder(new TcpDiscoveryVmIpFinder(true)); cfg.setDiscoverySpi(discoSpi); return cfg; } /** * Concatenates elements to an int array. * * @param arr Array. * @param obj One or more elements to concatenate. * @return Concatenated array. */ protected static int[] concat(@Nullable int[] arr, int... obj) { int[] newArr; if (arr == null || arr.length == 0) newArr = obj; else { newArr = Arrays.copyOf(arr, arr.length + obj.length); System.arraycopy(obj, 0, newArr, arr.length, obj.length); } return newArr; } /** {@inheritDoc} */ @Override protected void beforeTestsStarted() throws Exception { Ignite ignite = startGrid(1); igfs = (IgfsImpl) ignite.fileSystems().iterator().next(); } /** {@inheritDoc} */ @Override protected void afterTest() throws Exception { if (lsnr != null) { grid(1).events().stopLocalListen(lsnr, EVTS_IGFS); lsnr = null; } // Clean up file system. if (igfs != null) igfs.clear(); } /** {@inheritDoc} */ @Override protected void afterTestsStopped() throws Exception { stopGrid(1); } /** * Checks events on CRUD operations on a single file in nested directories. * * @throws Exception If failed. */ public void testSingleFileNestedDirs() throws Exception { final List<Event> evtList = new ArrayList<>(); final int evtsCnt = 6 + 1 + 1; final CountDownLatch latch = new CountDownLatch(evtsCnt); grid(1).events().localListen(lsnr = new IgnitePredicate<Event>() { @Override public boolean apply(Event evt) { log.info("Received event [evt=" + evt + ']'); evtList.add(evt); latch.countDown(); return true; } }, EVTS_IGFS); IgfsPath dir = new IgfsPath("/dir1/dir2/dir3"); IgfsPath file = new IgfsPath(dir, "file1"); // Will generate 3 EVT_IGFS_DIR_CREATED + EVT_IGFS_FILE_CREATED + EVT_IGFS_FILE_OPENED_WRITE + // EVT_IGFS_FILE_CLOSED and a number of EVT_IGFS_META_UPDATED. igfs.create(file, true).close(); IgfsPath mvFile = new IgfsPath(dir, "mvFile1"); igfs.rename(file, mvFile); // Will generate EVT_IGFS_FILE_RENAMED. // Will generate EVT_IGFS_DIR_DELETED event. assertTrue(igfs.delete(dir.parent(), true)); assertTrue(latch.await(10, TimeUnit.SECONDS)); assertEquals(evtsCnt, evtList.size()); IgfsEvent evt = (IgfsEvent)evtList.get(0); assertEquals(EVT_IGFS_DIR_CREATED, evt.type()); assertEquals(new IgfsPath("/dir1"), evt.path()); assertTrue(evt.isDirectory()); evt = (IgfsEvent)evtList.get(1); assertEquals(EVT_IGFS_DIR_CREATED, evt.type()); assertEquals(new IgfsPath("/dir1/dir2"), evt.path()); evt = (IgfsEvent)evtList.get(2); assertEquals(EVT_IGFS_DIR_CREATED, evt.type()); assertEquals(new IgfsPath("/dir1/dir2/dir3"), evt.path()); evt = (IgfsEvent)evtList.get(3); assertEquals(EVT_IGFS_FILE_CREATED, evt.type()); assertEquals(new IgfsPath("/dir1/dir2/dir3/file1"), evt.path()); assertFalse(evt.isDirectory()); evt = (IgfsEvent)evtList.get(4); assertEquals(EVT_IGFS_FILE_OPENED_WRITE, evt.type()); assertEquals(new IgfsPath("/dir1/dir2/dir3/file1"), evt.path()); evt = (IgfsEvent)evtList.get(5); assertEquals(EVT_IGFS_FILE_CLOSED_WRITE, evt.type()); assertEquals(new IgfsPath("/dir1/dir2/dir3/file1"), evt.path()); assertEquals(0, evt.dataSize()); evt = (IgfsEvent)evtList.get(6); assertEquals(EVT_IGFS_FILE_RENAMED, evt.type()); assertEquals(new IgfsPath("/dir1/dir2/dir3/file1"), evt.path()); assertEquals(new IgfsPath("/dir1/dir2/dir3/mvFile1"), evt.newPath()); evt = (IgfsEvent)evtList.get(7); assertEquals(EVT_IGFS_DIR_DELETED, evt.type()); assertEquals(new IgfsPath("/dir1/dir2"), evt.path()); } /** * Checks events on CRUD operations on a single directory * with some files. * * @throws Exception If failed. */ public void testDirWithFiles() throws Exception { final List<Event> evtList = new ArrayList<>(); final int evtsCnt = 4 + 3 + 1; final CountDownLatch latch = new CountDownLatch(evtsCnt); grid(1).events().localListen(lsnr = new IgnitePredicate<Event>() { @Override public boolean apply(Event evt) { log.info("Received event [evt=" + evt + ']'); evtList.add(evt); latch.countDown(); return true; } }, EVTS_IGFS); IgfsPath dir = new IgfsPath("/dir1"); IgfsPath file1 = new IgfsPath(dir, "file1"); IgfsPath file2 = new IgfsPath(dir, "file2"); // Will generate EVT_IGFS_DIR_CREATED + EVT_IGFS_FILE_CREATED + EVT_IGFS_FILE_OPENED_WRITE + // EVT_IGFS_FILE_CLOSED_WRITE. igfs.create(file1, true).close(); // Will generate EVT_IGFS_FILE_CREATED + EVT_IGFS_FILE_OPENED_WRITE + // EVT_IGFS_FILE_CLOSED. igfs.create(file2, true).close(); // Will generate EVT_IGFS_DIR_DELETED event. assertTrue(igfs.delete(dir, true)); assertTrue(latch.await(10, TimeUnit.SECONDS)); assertEquals(evtsCnt, evtList.size()); IgfsEvent evt = (IgfsEvent)evtList.get(0); assertEquals(EVT_IGFS_DIR_CREATED, evt.type()); assertEquals(new IgfsPath("/dir1"), evt.path()); assertTrue(evt.isDirectory()); evt = (IgfsEvent)evtList.get(1); assertEquals(EVT_IGFS_FILE_CREATED, evt.type()); assertEquals(new IgfsPath("/dir1/file1"), evt.path()); assertFalse(evt.isDirectory()); evt = (IgfsEvent)evtList.get(2); assertEquals(EVT_IGFS_FILE_OPENED_WRITE, evt.type()); assertEquals(new IgfsPath("/dir1/file1"), evt.path()); evt = (IgfsEvent)evtList.get(3); assertEquals(EVT_IGFS_FILE_CLOSED_WRITE, evt.type()); assertEquals(new IgfsPath("/dir1/file1"), evt.path()); evt = (IgfsEvent)evtList.get(4); assertEquals(EVT_IGFS_FILE_CREATED, evt.type()); assertEquals(new IgfsPath("/dir1/file2"), evt.path()); assertFalse(evt.isDirectory()); evt = (IgfsEvent)evtList.get(5); assertEquals(EVT_IGFS_FILE_OPENED_WRITE, evt.type()); assertEquals(new IgfsPath("/dir1/file2"), evt.path()); evt = (IgfsEvent)evtList.get(6); assertEquals(EVT_IGFS_FILE_CLOSED_WRITE, evt.type()); assertEquals(new IgfsPath("/dir1/file2"), evt.path()); evt = (IgfsEvent)evtList.get(7); assertEquals(EVT_IGFS_DIR_DELETED, evt.type()); assertEquals(new IgfsPath("/dir1"), evt.path()); } /** * Checks events on CRUD operations on a single empty * directory. * * @throws Exception If failed. */ public void testSingleEmptyDir() throws Exception { final List<Event> evtList = new ArrayList<>(); final int evtsCnt = 1 + 1 + 0 + 1; final CountDownLatch latch = new CountDownLatch(evtsCnt); grid(1).events().localListen(lsnr = new IgnitePredicate<Event>() { @Override public boolean apply(Event evt) { log.info("Received event [evt=" + evt + ']'); evtList.add(evt); latch.countDown(); return true; } }, EVTS_IGFS); IgfsPath dir = new IgfsPath("/dir1"); igfs.mkdirs(dir); // Will generate EVT_IGFS_DIR_CREATED. IgfsPath mvDir = new IgfsPath("/mvDir1"); igfs.rename(dir, mvDir); // Will generate EVT_IGFS_DIR_RENAMED. assertFalse(igfs.delete(dir, true)); // Will generate no event. assertTrue(igfs.delete(mvDir, true)); // Will generate EVT_IGFS_DIR_DELETED events. assertTrue(latch.await(10, TimeUnit.SECONDS)); assertEquals(evtsCnt, evtList.size()); IgfsEvent evt = (IgfsEvent)evtList.get(0); assertEquals(EVT_IGFS_DIR_CREATED, evt.type()); assertEquals(new IgfsPath("/dir1"), evt.path()); assertTrue(evt.isDirectory()); evt = (IgfsEvent)evtList.get(1); assertEquals(EVT_IGFS_DIR_RENAMED, evt.type()); assertEquals(new IgfsPath("/dir1"), evt.path()); assertEquals(new IgfsPath("/mvDir1"), evt.newPath()); assertTrue(evt.isDirectory()); evt = (IgfsEvent)evtList.get(2); assertEquals(EVT_IGFS_DIR_DELETED, evt.type()); assertEquals(new IgfsPath("/mvDir1"), evt.path()); assertTrue(evt.isDirectory()); } /** * Checks events on CRUD operations on 2 files. * * @throws Exception If failed. */ public void testTwoFiles() throws Exception { final List<Event> evtList = new ArrayList<>(); final int evtsCnt = 4 + 3 + 2 + 2; final CountDownLatch latch = new CountDownLatch(evtsCnt); grid(1).events().localListen(lsnr = new IgnitePredicate<Event>() { @Override public boolean apply(Event evt) { log.info("Received event [evt=" + evt + ']'); evtList.add(evt); latch.countDown(); return true; } }, EVTS_IGFS); IgfsPath dir = new IgfsPath("/dir1"); IgfsPath file1 = new IgfsPath(dir, "file1"); // Will generate EVT_IGFS_FILE_CREATED event + EVT_IGFS_DIR_CREATED event + OPEN + CLOSE. igfs.create(file1, true).close(); IgfsPath file2 = new IgfsPath(dir, "file2"); igfs.create(file2, true).close(); // Will generate 1 EVT_IGFS_FILE_CREATED event + OPEN + CLOSE. assertTrue(igfs.exists(dir)); assertTrue(igfs.exists(file1)); assertTrue(igfs.exists(file2)); assertTrue(igfs.delete(file1, false)); // Will generate 1 EVT_IGFS_FILE_DELETED and 1 EVT_IGFS_FILE_PURGED. assertTrue(igfs.delete(file2, false)); // Same. assertTrue(latch.await(10, TimeUnit.SECONDS)); assertEquals(evtsCnt, evtList.size()); IgfsEvent evt = (IgfsEvent)evtList.get(0); assertEquals(EVT_IGFS_DIR_CREATED, evt.type()); assertEquals(new IgfsPath("/dir1"), evt.path()); assertTrue(evt.isDirectory()); evt = (IgfsEvent)evtList.get(1); assertEquals(EVT_IGFS_FILE_CREATED, evt.type()); assertEquals(new IgfsPath("/dir1/file1"), evt.path()); evt = (IgfsEvent)evtList.get(2); assertEquals(EVT_IGFS_FILE_OPENED_WRITE, evt.type()); assertEquals(new IgfsPath("/dir1/file1"), evt.path()); evt = (IgfsEvent)evtList.get(3); assertEquals(EVT_IGFS_FILE_CLOSED_WRITE, evt.type()); assertEquals(new IgfsPath("/dir1/file1"), evt.path()); assertEquals(0, evt.dataSize()); evt = (IgfsEvent)evtList.get(4); assertEquals(EVT_IGFS_FILE_CREATED, evt.type()); assertEquals(new IgfsPath("/dir1/file2"), evt.path()); evt = (IgfsEvent)evtList.get(5); assertEquals(EVT_IGFS_FILE_OPENED_WRITE, evt.type()); assertEquals(new IgfsPath("/dir1/file2"), evt.path()); evt = (IgfsEvent)evtList.get(6); assertEquals(EVT_IGFS_FILE_CLOSED_WRITE, evt.type()); assertEquals(new IgfsPath("/dir1/file2"), evt.path()); assertEquals(0, evt.dataSize()); assertOneToOne( evtList.subList(7, 11), new EventPredicate(EVT_IGFS_FILE_DELETED, new IgfsPath("/dir1/file1")), new EventPredicate(EVT_IGFS_FILE_PURGED, new IgfsPath("/dir1/file1")), new EventPredicate(EVT_IGFS_FILE_DELETED, new IgfsPath("/dir1/file2")), new EventPredicate(EVT_IGFS_FILE_PURGED, new IgfsPath("/dir1/file2")) ); } /** * Checks events on CRUD operations with non-recursive * directory deletion. * * @throws Exception If failed. */ public void testDeleteNonRecursive() throws Exception { final List<Event> evtList = new ArrayList<>(); final int evtsCnt = 2 + 0 + 1; final CountDownLatch latch = new CountDownLatch(evtsCnt); grid(1).events().localListen(lsnr = new IgnitePredicate<Event>() { @Override public boolean apply(Event evt) { log.info("Received event [evt=" + evt + ']'); evtList.add(evt); latch.countDown(); return true; } }, EVTS_IGFS); IgfsPath dir = new IgfsPath("/dir1/dir2"); igfs.mkdirs(dir); // Will generate 2 EVT_IGFS_DIR_CREATED events. try { igfs.delete(dir.parent(), false); // Will generate no events. } catch (IgniteException ignore) { // No-op. } assertTrue(igfs.delete(dir, false)); // Will generate 1 EVT_IGFS_DIR_DELETED event. assertTrue(latch.await(10, TimeUnit.SECONDS)); assertEquals(evtsCnt, evtList.size()); IgfsEvent evt = (IgfsEvent)evtList.get(0); assertEquals(EVT_IGFS_DIR_CREATED, evt.type()); assertEquals(new IgfsPath("/dir1"), evt.path()); evt = (IgfsEvent)evtList.get(1); assertEquals(EVT_IGFS_DIR_CREATED, evt.type()); assertEquals(new IgfsPath("/dir1/dir2"), evt.path()); IgfsEvent evt3 = (IgfsEvent)evtList.get(2); assertEquals(EVT_IGFS_DIR_DELETED, evt3.type()); assertEquals(new IgfsPath("/dir1/dir2"), evt3.path()); } /** * Checks events on CRUD operations on file move. * * @throws Exception If failed. */ public void testMoveFile() throws Exception { final List<Event> evtList = new ArrayList<>(); final int evtsCnt = 5 + 1; final CountDownLatch latch = new CountDownLatch(evtsCnt); grid(1).events().localListen(lsnr = new IgnitePredicate<Event>() { @Override public boolean apply(Event evt) { log.info("Received event [evt=" + evt + ']'); evtList.add(evt); latch.countDown(); return true; } }, EVTS_IGFS); IgfsPath dir = new IgfsPath("/dir1/dir2"); IgfsPath file = new IgfsPath(dir, "file1"); // Will generate 2 EVT_IGFS_DIR_CREATED events + EVT_IGFS_FILE_CREATED_EVENT + OPEN + CLOSE. igfs.create(file, true).close(); igfs.rename(file, dir.parent()); // Will generate 1 EVT_IGFS_FILE_RENAMED. assertTrue(igfs.exists(new IgfsPath(dir.parent(), file.name()))); assertTrue(latch.await(10, TimeUnit.SECONDS)); assertEquals(evtsCnt, evtList.size()); IgfsEvent evt = (IgfsEvent)evtList.get(0); assertEquals(EVT_IGFS_DIR_CREATED, evt.type()); assertEquals(new IgfsPath("/dir1"), evt.path()); evt = (IgfsEvent)evtList.get(1); assertEquals(EVT_IGFS_DIR_CREATED, evt.type()); assertEquals(new IgfsPath("/dir1/dir2"), evt.path()); evt = (IgfsEvent)evtList.get(2); assertEquals(EVT_IGFS_FILE_CREATED, evt.type()); assertEquals(new IgfsPath("/dir1/dir2/file1"), evt.path()); evt = (IgfsEvent)evtList.get(3); assertEquals(EVT_IGFS_FILE_OPENED_WRITE, evt.type()); assertEquals(new IgfsPath("/dir1/dir2/file1"), evt.path()); evt = (IgfsEvent)evtList.get(4); assertEquals(EVT_IGFS_FILE_CLOSED_WRITE, evt.type()); assertEquals(new IgfsPath("/dir1/dir2/file1"), evt.path()); assertEquals(0, evt.dataSize()); IgfsEvent evt4 = (IgfsEvent)evtList.get(5); assertEquals(EVT_IGFS_FILE_RENAMED, evt4.type()); assertEquals(new IgfsPath("/dir1/dir2/file1"), evt4.path()); assertEquals(new IgfsPath("/dir1/file1"), evt4.newPath()); } /** * Checks events on CRUD operations with multiple * empty directories. * * @throws Exception If failed. */ public void testNestedEmptyDirs() throws Exception { final List<Event> evtList = new ArrayList<>(); final int evtsCnt = 2 + 1; final CountDownLatch latch = new CountDownLatch(evtsCnt); grid(1).events().localListen(lsnr = new IgnitePredicate<Event>() { @Override public boolean apply(Event evt) { log.info("Received event [evt=" + evt + ']'); evtList.add(evt); latch.countDown(); return true; } }, EVTS_IGFS); IgfsPath dir = new IgfsPath("/dir1/dir2"); assertFalse(igfs.exists(dir.parent())); igfs.mkdirs(dir); // Will generate 2 EVT_IGFS_DIR_RENAMED events. assertTrue(igfs.delete(dir.parent(), true)); // Will generate EVT_IGFS_DIR_DELETED event. assertTrue(latch.await(10, TimeUnit.SECONDS)); assertEquals(evtsCnt, evtList.size()); IgfsEvent evt = (IgfsEvent)evtList.get(0); assertEquals(EVT_IGFS_DIR_CREATED, evt.type()); assertEquals(new IgfsPath("/dir1"), evt.path()); evt = (IgfsEvent)evtList.get(1); assertEquals(EVT_IGFS_DIR_CREATED, evt.type()); assertEquals(new IgfsPath("/dir1/dir2"), evt.path()); evt = (IgfsEvent)evtList.get(2); assertEquals(EVT_IGFS_DIR_DELETED, evt.type()); assertEquals(new IgfsPath("/dir1"), evt.path()); } /** * Checks events on CRUD operations with single * file overwrite. * * @throws Exception If failed. */ public void testSingleFileOverwrite() throws Exception { final List<Event> evtList = new ArrayList<>(); // NB: In case of create-overwrite FILE_PURGED event will be sent in PRIMARY IGFS mode only. final boolean awaitForPurgeEvt = grid(1).configuration().getFileSystemConfiguration()[0].getDefaultMode() == IgfsMode.PRIMARY; final int evtsCnt = 1 + 4 + (awaitForPurgeEvt ? 1 : 0); final CountDownLatch latch = new CountDownLatch(evtsCnt); grid(1).events().localListen(lsnr = new IgnitePredicate<Event>() { @Override public boolean apply(Event evt) { log.info("Received event [evt=" + evt + ']'); evtList.add(evt); latch.countDown(); return true; } }, EVTS_IGFS); final IgfsPath file = new IgfsPath("/file1"); igfs.create(file, false).close(); // Will generate create, open and close events. igfs.create(file, true).close(); // Will generate PURGE (async), OPEN_WRITE & close events. try { igfs.create(file, false).close(); // Won't generate any event. } catch (Exception ignore) { // No-op. } assertTrue(latch.await(10, TimeUnit.SECONDS)); assertEquals(evtsCnt, evtList.size()); final IgfsPath file1 = new IgfsPath("/file1"); IgfsEvent evt = (IgfsEvent)evtList.get(0); assertEquals(EVT_IGFS_FILE_CREATED, evt.type()); assertEquals(file1, evt.path()); evt = (IgfsEvent)evtList.get(1); assertEquals(EVT_IGFS_FILE_OPENED_WRITE, evt.type()); assertEquals(file1, evt.path()); evt = (IgfsEvent)evtList.get(2); assertEquals(EVT_IGFS_FILE_CLOSED_WRITE, evt.type()); assertEquals(file1, evt.path()); assertEquals(0, evt.dataSize()); assertOneToOne( evtList.subList(3, evtsCnt), new P1<Event>() { @Override public boolean apply(Event e) { IgfsEvent e0 = (IgfsEvent)e; return e0.type() == EVT_IGFS_FILE_PURGED && e0.path().equals(file1); } }, new P1<Event>() { @Override public boolean apply(Event e) { IgfsEvent e0 = (IgfsEvent)e; return e0.type() == EVT_IGFS_FILE_OPENED_WRITE && e0.path().equals(file1); } }, new P1<Event>() { @Override public boolean apply(Event e) { IgfsEvent e0 = (IgfsEvent)e; return e0.type() == EVT_IGFS_FILE_CLOSED_WRITE && e0.path().equals(file1); } } ); } /** * Checks events on file data transfer operations. * * @throws Exception If failed. */ public void testFileDataEvents() throws Exception { final List<Event> evtList = new ArrayList<>(); final int evtsCnt = 5; final CountDownLatch latch = new CountDownLatch(evtsCnt); grid(1).events().localListen(lsnr = new IgnitePredicate<Event>() { @Override public boolean apply(Event evt) { log.info("Received event [evt=" + evt + ']'); evtList.add(evt); latch.countDown(); return true; } }, EVTS_IGFS); final IgfsPath file = new IgfsPath("/file1"); final int dataSize = 1024; byte[] buf = new byte[dataSize]; // Will generate IGFS_FILE_CREATED, IGFS_FILE_OPENED_WRITE, IGFS_FILE_CLOSED_WRITE. try (IgfsOutputStream os = igfs.create(file, false)) { os.write(buf); // Will generate no events. } // Will generate EVT_IGFS_FILE_OPENED_READ, IGFS_FILE_CLOSED_READ. try (IgfsInputStream is = igfs.open(file, 256)) { is.readFully(0, buf); // Will generate no events. } assertTrue(latch.await(10, TimeUnit.SECONDS)); assertEquals(evtsCnt, evtList.size()); IgfsEvent evt = (IgfsEvent)evtList.get(0); assertEquals(EVT_IGFS_FILE_CREATED, evt.type()); assertEquals(new IgfsPath("/file1"), evt.path()); evt = (IgfsEvent)evtList.get(1); assertEquals(EVT_IGFS_FILE_OPENED_WRITE, evt.type()); assertEquals(new IgfsPath("/file1"), evt.path()); evt = (IgfsEvent)evtList.get(2); assertEquals(EVT_IGFS_FILE_CLOSED_WRITE, evt.type()); assertEquals(new IgfsPath("/file1"), evt.path()); assertEquals((long)dataSize, evt.dataSize()); evt = (IgfsEvent)evtList.get(3); assertEquals(EVT_IGFS_FILE_OPENED_READ, evt.type()); assertEquals(new IgfsPath("/file1"), evt.path()); evt = (IgfsEvent)evtList.get(4); assertEquals(EVT_IGFS_FILE_CLOSED_READ, evt.type()); assertEquals(new IgfsPath("/file1"), evt.path()); assertEquals((long) dataSize, evt.dataSize()); } /** * Predicate for matching {@link org.apache.ignite.events.IgfsEvent}. */ private static class EventPredicate implements IgnitePredicate<Event> { /** */ private final int evt; /** */ private final IgfsPath path; /** * @param evt Event type. * @param path IGFS path. */ EventPredicate(int evt, IgfsPath path) { this.evt = evt; this.path = path; } /** {@inheritDoc} */ @Override public boolean apply(Event e) { IgfsEvent e0 = (IgfsEvent)e; return e0.type() == evt && e0.path().equals(path); } } }