You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@flink.apache.org by kl0u <gi...@git.apache.org> on 2016/10/05 08:21:28 UTC

[GitHub] flink pull request #2593: [FLINK-4329] Fix Streaming File Source Timestamps/...

GitHub user kl0u opened a pull request:

    https://github.com/apache/flink/pull/2593

    [FLINK-4329] Fix Streaming File Source Timestamps/Watermarks Handling

    This is a quick fix for the [FLINK-4329] issue. The fix on the master is different but it contains more changes that are not easy to back-port to 1.1.

You can merge this pull request into a Git repository by running:

    $ git pull https://github.com/kl0u/flink injestion_fix_1.1

Alternatively you can review and apply these changes as the patch at:

    https://github.com/apache/flink/pull/2593.patch

To close this pull request, make a commit to your master/trunk branch
with (at least) the following in the commit message:

    This closes #2593
    
----
commit 79d48e77b4a9c8a8eaf4e1e3199e2787deebab63
Author: kl0u <kk...@gmail.com>
Date:   2016-10-04T13:27:59Z

    [FLINK-4329] Fix Streaming File Source Timestamps/Watermarks Handling

----


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #2593: [FLINK-4329] Fix Streaming File Source Timestamps/...

Posted by kl0u <gi...@git.apache.org>.
Github user kl0u closed the pull request at:

    https://github.com/apache/flink/pull/2593


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #2593: [FLINK-4329] Fix Streaming File Source Timestamps/...

Posted by mxm <gi...@git.apache.org>.
Github user mxm commented on a diff in the pull request:

    https://github.com/apache/flink/pull/2593#discussion_r81947121
  
    --- Diff: flink-streaming-java/src/main/java/org/apache/flink/streaming/api/operators/StreamSource.java ---
    @@ -299,7 +319,7 @@ public void trigger(long timestamp) {
     					synchronized (lockingObject) {
     						if (currentTime > nextWatermarkTime) {
     							output.emitWatermark(new Watermark(watermarkTime));
    -							nextWatermarkTime += watermarkInterval;
    +							nextWatermarkTime = watermarkTime + watermarkInterval;
    --- End diff --
    
    Is this a fix? Does it change the semantics?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #2593: [FLINK-4329] Fix Streaming File Source Timestamps/...

Posted by mxm <gi...@git.apache.org>.
Github user mxm commented on a diff in the pull request:

    https://github.com/apache/flink/pull/2593#discussion_r81944308
  
    --- Diff: flink-fs-tests/src/test/java/org/apache/flink/hdfstests/ContinuousFileMonitoringTest.java ---
    @@ -106,6 +107,155 @@ public static void destroyHDFS() {
     	//						TESTS
     
     	@Test
    +	public void testFileReadingOperatorWithIngestionTime() throws Exception {
    +		Set<org.apache.hadoop.fs.Path> filesCreated = new HashSet<>();
    +		Map<Integer, String> expectedFileContents = new HashMap<>();
    +
    +		for(int i = 0; i < NO_OF_FILES; i++) {
    +			Tuple2<org.apache.hadoop.fs.Path, String> file = fillWithData(hdfsURI, "file", i, "This is test line.");
    +			filesCreated.add(file.f0);
    +			expectedFileContents.put(i, file.f1);
    +		}
    +
    +		TextInputFormat format = new TextInputFormat(new Path(hdfsURI));
    +		TypeInformation<String> typeInfo = TypeExtractor.getInputFormatTypes(format);
    +
    +		final long watermarkInterval = 10;
    +		ExecutionConfig executionConfig = new ExecutionConfig();
    +		executionConfig.setAutoWatermarkInterval(watermarkInterval);
    +
    +		ContinuousFileReaderOperator<String, ?> reader = new ContinuousFileReaderOperator<>(format);
    +		reader.setOutputType(typeInfo, executionConfig);
    +
    +		final TestTimeServiceProvider timeServiceProvider = new TestTimeServiceProvider();
    +		final OneInputStreamOperatorTestHarness<FileInputSplit, String> tester =
    +			new OneInputStreamOperatorTestHarness<>(reader, executionConfig, timeServiceProvider);
    +		tester.setTimeCharacteristic(TimeCharacteristic.IngestionTime);
    +		tester.open();
    +
    +		Assert.assertEquals(TimeCharacteristic.IngestionTime, tester.getTimeCharacteristic());
    +
    +		// test that watermarks are correctly emitted
    +
    +		timeServiceProvider.setCurrentTime(201);
    +		timeServiceProvider.setCurrentTime(301);
    +		timeServiceProvider.setCurrentTime(401);
    +		timeServiceProvider.setCurrentTime(501);
    +
    +		int i = 0;
    +		for(Object line: tester.getOutput()) {
    +			if (!(line instanceof Watermark)) {
    +				Assert.fail("Only watermarks are expected here ");
    +			}
    +			Watermark w = (Watermark) line;
    +			Assert.assertEquals(200 + (i * 100), w.getTimestamp());
    +			i++;
    +		}
    +
    +		// clear the output to get the elements only and the final watermark
    +		tester.getOutput().clear();
    +		Assert.assertEquals(0, tester.getOutput().size());
    +
    +		// create the necessary splits for the test
    +		FileInputSplit[] splits = format.createInputSplits(
    +			reader.getRuntimeContext().getNumberOfParallelSubtasks());
    +
    +		// and feed them to the operator
    +		Map<Integer, List<String>> actualFileContents = new HashMap<>();
    +
    +		long lastSeenWatermark = Long.MIN_VALUE;
    +		int lineCounter = 0;	// counter for the lines read from the splits
    +		int watermarkCounter = 0;
    +
    +		for(FileInputSplit split: splits) {
    +
    +			// set the next "current processing time".
    +			long nextTimestamp = timeServiceProvider.getCurrentProcessingTime() + watermarkInterval;
    +			timeServiceProvider.setCurrentTime(nextTimestamp);
    +
    +			// send the next split to be read and wait until it is fully read.
    +			tester.processElement(new StreamRecord<>(split));
    +			synchronized (tester.getCheckpointLock()) {
    +				while (tester.getOutput().isEmpty() || tester.getOutput().size() != (LINES_PER_FILE + 1)) {
    +					tester.getCheckpointLock().wait(10);
    +				}
    +			}
    +
    +			// verify that the results are the expected
    +			for(Object line: tester.getOutput()) {
    +				if (line instanceof StreamRecord) {
    +					StreamRecord<String> element = (StreamRecord<String>) line;
    +					lineCounter++;
    +
    +					Assert.assertEquals(nextTimestamp, element.getTimestamp());
    +
    +					int fileIdx = Character.getNumericValue(element.getValue().charAt(0));
    +					List<String> content = actualFileContents.get(fileIdx);
    +					if (content == null) {
    +						content = new ArrayList<>();
    +						actualFileContents.put(fileIdx, content);
    +					}
    +					content.add(element.getValue() + "\n");
    +				} else if (line instanceof Watermark) {
    +					long watermark = ((Watermark) line).getTimestamp();
    +
    +					Assert.assertEquals(nextTimestamp - (nextTimestamp % watermarkInterval), watermark);
    +					Assert.assertTrue(watermark > lastSeenWatermark);
    +					watermarkCounter++;
    +
    +					lastSeenWatermark = watermark;
    +				} else {
    +					Assert.fail("Unknown element in the list.");
    +				}
    +			}
    +
    +			// clean the output to be ready for the next split
    +			tester.getOutput().clear();
    +		}
    +
    +		// now we are processing one split after the other,
    +		// so all the elements must be here by now.
    +		Assert.assertEquals(NO_OF_FILES * LINES_PER_FILE, lineCounter);
    +
    +		// because we expect one watermark per split.
    +		Assert.assertEquals(NO_OF_FILES, watermarkCounter);
    +
    +		// then close the reader gracefully so that the Long.MAX watermark is emitted
    +		synchronized (tester.getCheckpointLock()) {
    +			tester.close();
    --- End diff --
    
    I don't think you need to lock on the checkpoint lock here.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #2593: [FLINK-4329] Fix Streaming File Source Timestamps/...

Posted by mxm <gi...@git.apache.org>.
Github user mxm commented on a diff in the pull request:

    https://github.com/apache/flink/pull/2593#discussion_r81944020
  
    --- Diff: flink-fs-tests/src/test/java/org/apache/flink/hdfstests/ContinuousFileMonitoringTest.java ---
    @@ -106,6 +107,155 @@ public static void destroyHDFS() {
     	//						TESTS
     
     	@Test
    +	public void testFileReadingOperatorWithIngestionTime() throws Exception {
    +		Set<org.apache.hadoop.fs.Path> filesCreated = new HashSet<>();
    +		Map<Integer, String> expectedFileContents = new HashMap<>();
    +
    +		for(int i = 0; i < NO_OF_FILES; i++) {
    +			Tuple2<org.apache.hadoop.fs.Path, String> file = fillWithData(hdfsURI, "file", i, "This is test line.");
    +			filesCreated.add(file.f0);
    +			expectedFileContents.put(i, file.f1);
    +		}
    +
    +		TextInputFormat format = new TextInputFormat(new Path(hdfsURI));
    +		TypeInformation<String> typeInfo = TypeExtractor.getInputFormatTypes(format);
    +
    +		final long watermarkInterval = 10;
    +		ExecutionConfig executionConfig = new ExecutionConfig();
    +		executionConfig.setAutoWatermarkInterval(watermarkInterval);
    +
    +		ContinuousFileReaderOperator<String, ?> reader = new ContinuousFileReaderOperator<>(format);
    +		reader.setOutputType(typeInfo, executionConfig);
    +
    +		final TestTimeServiceProvider timeServiceProvider = new TestTimeServiceProvider();
    +		final OneInputStreamOperatorTestHarness<FileInputSplit, String> tester =
    +			new OneInputStreamOperatorTestHarness<>(reader, executionConfig, timeServiceProvider);
    +		tester.setTimeCharacteristic(TimeCharacteristic.IngestionTime);
    +		tester.open();
    +
    +		Assert.assertEquals(TimeCharacteristic.IngestionTime, tester.getTimeCharacteristic());
    +
    +		// test that watermarks are correctly emitted
    +
    +		timeServiceProvider.setCurrentTime(201);
    +		timeServiceProvider.setCurrentTime(301);
    +		timeServiceProvider.setCurrentTime(401);
    +		timeServiceProvider.setCurrentTime(501);
    +
    +		int i = 0;
    +		for(Object line: tester.getOutput()) {
    +			if (!(line instanceof Watermark)) {
    +				Assert.fail("Only watermarks are expected here ");
    +			}
    +			Watermark w = (Watermark) line;
    +			Assert.assertEquals(200 + (i * 100), w.getTimestamp());
    +			i++;
    +		}
    +
    +		// clear the output to get the elements only and the final watermark
    +		tester.getOutput().clear();
    +		Assert.assertEquals(0, tester.getOutput().size());
    +
    +		// create the necessary splits for the test
    +		FileInputSplit[] splits = format.createInputSplits(
    +			reader.getRuntimeContext().getNumberOfParallelSubtasks());
    +
    +		// and feed them to the operator
    +		Map<Integer, List<String>> actualFileContents = new HashMap<>();
    +
    +		long lastSeenWatermark = Long.MIN_VALUE;
    +		int lineCounter = 0;	// counter for the lines read from the splits
    +		int watermarkCounter = 0;
    +
    +		for(FileInputSplit split: splits) {
    +
    +			// set the next "current processing time".
    +			long nextTimestamp = timeServiceProvider.getCurrentProcessingTime() + watermarkInterval;
    +			timeServiceProvider.setCurrentTime(nextTimestamp);
    +
    +			// send the next split to be read and wait until it is fully read.
    +			tester.processElement(new StreamRecord<>(split));
    +			synchronized (tester.getCheckpointLock()) {
    +				while (tester.getOutput().isEmpty() || tester.getOutput().size() != (LINES_PER_FILE + 1)) {
    +					tester.getCheckpointLock().wait(10);
    --- End diff --
    
    Seems like you don't need to synchronize on the checkpoint lock here and you simply want to `Thread.sleep(10)` to give the SplitReader thread more time to read. Perhaps add a comment to explain the +1.
    
    ```java
    while (tester.getOutput().size() < (LINES_PER_FILE + 1)) {
        // wait for all lines of this split to be read and the watermark to be emitted
        Thread.sleep(10);
    }
    ```
    should be enough.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #2593: [FLINK-4329] Fix Streaming File Source Timestamps/...

Posted by mxm <gi...@git.apache.org>.
Github user mxm commented on a diff in the pull request:

    https://github.com/apache/flink/pull/2593#discussion_r81947893
  
    --- Diff: flink-fs-tests/src/test/java/org/apache/flink/hdfstests/ContinuousFileMonitoringTest.java ---
    @@ -106,6 +107,155 @@ public static void destroyHDFS() {
     	//						TESTS
     
     	@Test
    +	public void testFileReadingOperatorWithIngestionTime() throws Exception {
    +		Set<org.apache.hadoop.fs.Path> filesCreated = new HashSet<>();
    +		Map<Integer, String> expectedFileContents = new HashMap<>();
    +
    +		for(int i = 0; i < NO_OF_FILES; i++) {
    +			Tuple2<org.apache.hadoop.fs.Path, String> file = fillWithData(hdfsURI, "file", i, "This is test line.");
    +			filesCreated.add(file.f0);
    +			expectedFileContents.put(i, file.f1);
    +		}
    +
    +		TextInputFormat format = new TextInputFormat(new Path(hdfsURI));
    +		TypeInformation<String> typeInfo = TypeExtractor.getInputFormatTypes(format);
    +
    +		final long watermarkInterval = 10;
    +		ExecutionConfig executionConfig = new ExecutionConfig();
    +		executionConfig.setAutoWatermarkInterval(watermarkInterval);
    +
    +		ContinuousFileReaderOperator<String, ?> reader = new ContinuousFileReaderOperator<>(format);
    +		reader.setOutputType(typeInfo, executionConfig);
    +
    +		final TestTimeServiceProvider timeServiceProvider = new TestTimeServiceProvider();
    +		final OneInputStreamOperatorTestHarness<FileInputSplit, String> tester =
    +			new OneInputStreamOperatorTestHarness<>(reader, executionConfig, timeServiceProvider);
    +		tester.setTimeCharacteristic(TimeCharacteristic.IngestionTime);
    +		tester.open();
    +
    +		Assert.assertEquals(TimeCharacteristic.IngestionTime, tester.getTimeCharacteristic());
    +
    +		// test that watermarks are correctly emitted
    +
    +		timeServiceProvider.setCurrentTime(201);
    +		timeServiceProvider.setCurrentTime(301);
    +		timeServiceProvider.setCurrentTime(401);
    +		timeServiceProvider.setCurrentTime(501);
    +
    +		int i = 0;
    +		for(Object line: tester.getOutput()) {
    +			if (!(line instanceof Watermark)) {
    +				Assert.fail("Only watermarks are expected here ");
    +			}
    +			Watermark w = (Watermark) line;
    +			Assert.assertEquals(200 + (i * 100), w.getTimestamp());
    +			i++;
    +		}
    +
    +		// clear the output to get the elements only and the final watermark
    +		tester.getOutput().clear();
    +		Assert.assertEquals(0, tester.getOutput().size());
    +
    +		// create the necessary splits for the test
    +		FileInputSplit[] splits = format.createInputSplits(
    +			reader.getRuntimeContext().getNumberOfParallelSubtasks());
    +
    +		// and feed them to the operator
    +		Map<Integer, List<String>> actualFileContents = new HashMap<>();
    +
    +		long lastSeenWatermark = Long.MIN_VALUE;
    +		int lineCounter = 0;	// counter for the lines read from the splits
    +		int watermarkCounter = 0;
    +
    +		for(FileInputSplit split: splits) {
    +
    +			// set the next "current processing time".
    +			long nextTimestamp = timeServiceProvider.getCurrentProcessingTime() + watermarkInterval;
    +			timeServiceProvider.setCurrentTime(nextTimestamp);
    +
    +			// send the next split to be read and wait until it is fully read.
    +			tester.processElement(new StreamRecord<>(split));
    +			synchronized (tester.getCheckpointLock()) {
    +				while (tester.getOutput().isEmpty() || tester.getOutput().size() != (LINES_PER_FILE + 1)) {
    +					tester.getCheckpointLock().wait(10);
    +				}
    +			}
    +
    +			// verify that the results are the expected
    +			for(Object line: tester.getOutput()) {
    +				if (line instanceof StreamRecord) {
    +					StreamRecord<String> element = (StreamRecord<String>) line;
    +					lineCounter++;
    +
    +					Assert.assertEquals(nextTimestamp, element.getTimestamp());
    +
    +					int fileIdx = Character.getNumericValue(element.getValue().charAt(0));
    +					List<String> content = actualFileContents.get(fileIdx);
    +					if (content == null) {
    +						content = new ArrayList<>();
    +						actualFileContents.put(fileIdx, content);
    +					}
    +					content.add(element.getValue() + "\n");
    +				} else if (line instanceof Watermark) {
    +					long watermark = ((Watermark) line).getTimestamp();
    +
    +					Assert.assertEquals(nextTimestamp - (nextTimestamp % watermarkInterval), watermark);
    +					Assert.assertTrue(watermark > lastSeenWatermark);
    +					watermarkCounter++;
    +
    +					lastSeenWatermark = watermark;
    +				} else {
    +					Assert.fail("Unknown element in the list.");
    +				}
    +			}
    +
    +			// clean the output to be ready for the next split
    +			tester.getOutput().clear();
    +		}
    +
    +		// now we are processing one split after the other,
    +		// so all the elements must be here by now.
    +		Assert.assertEquals(NO_OF_FILES * LINES_PER_FILE, lineCounter);
    +
    +		// because we expect one watermark per split.
    +		Assert.assertEquals(NO_OF_FILES, watermarkCounter);
    +
    +		// then close the reader gracefully so that the Long.MAX watermark is emitted
    +		synchronized (tester.getCheckpointLock()) {
    +			tester.close();
    --- End diff --
    
    Never mind. Actually, `close()` expects as to hold the lock.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink issue #2593: [FLINK-4329] Fix Streaming File Source Timestamps/Waterma...

Posted by kl0u <gi...@git.apache.org>.
Github user kl0u commented on the issue:

    https://github.com/apache/flink/pull/2593
  
    Thanks @mxm and @StephanEwen for the comments. I have updated the PR.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #2593: [FLINK-4329] Fix Streaming File Source Timestamps/...

Posted by kl0u <gi...@git.apache.org>.
Github user kl0u commented on a diff in the pull request:

    https://github.com/apache/flink/pull/2593#discussion_r81995575
  
    --- Diff: flink-streaming-java/src/main/java/org/apache/flink/streaming/api/operators/StreamSource.java ---
    @@ -214,14 +216,26 @@ public AutomaticWatermarkContext(
     			this.watermarkInterval = watermarkInterval;
     			this.reuse = new StreamRecord<T>(null);
     
    +			// if it is a source, then we cast and cache it
    +			// here so that we do not have to do it in every collect(),
    +			// collectWithTimestamp() and emitWatermark()
    +
    +			if (!(owner instanceof AsyncExceptionChecker)) {
    +				throw new IllegalStateException("The ManualWatermarkContext can only be used " +
    +					"with sources that implement the AsyncExceptionChecker interface.");
    +			}
    +			this.source = (AsyncExceptionChecker) owner;
    +
     			long now = owner.getCurrentProcessingTime();
     			this.watermarkTimer = owner.registerTimer(now + watermarkInterval,
     				new WatermarkEmittingTask(owner, lockingObjectParam, outputParam));
     		}
     
     		@Override
     		public void collect(T element) {
    -			owner.checkAsyncException();
    +			if (source != null) {
    --- End diff --
    
    You are right. I fixed it!


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink issue #2593: [FLINK-4329] Fix Streaming File Source Timestamps/Waterma...

Posted by mxm <gi...@git.apache.org>.
Github user mxm commented on the issue:

    https://github.com/apache/flink/pull/2593
  
    Thanks! Merged. Could you close the PR?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #2593: [FLINK-4329] Fix Streaming File Source Timestamps/...

Posted by mxm <gi...@git.apache.org>.
Github user mxm commented on a diff in the pull request:

    https://github.com/apache/flink/pull/2593#discussion_r81944676
  
    --- Diff: flink-fs-tests/src/test/java/org/apache/flink/hdfstests/ContinuousFileMonitoringTest.java ---
    @@ -106,6 +107,155 @@ public static void destroyHDFS() {
     	//						TESTS
     
     	@Test
    +	public void testFileReadingOperatorWithIngestionTime() throws Exception {
    +		Set<org.apache.hadoop.fs.Path> filesCreated = new HashSet<>();
    +		Map<Integer, String> expectedFileContents = new HashMap<>();
    +
    +		for(int i = 0; i < NO_OF_FILES; i++) {
    +			Tuple2<org.apache.hadoop.fs.Path, String> file = fillWithData(hdfsURI, "file", i, "This is test line.");
    +			filesCreated.add(file.f0);
    +			expectedFileContents.put(i, file.f1);
    +		}
    +
    +		TextInputFormat format = new TextInputFormat(new Path(hdfsURI));
    +		TypeInformation<String> typeInfo = TypeExtractor.getInputFormatTypes(format);
    +
    +		final long watermarkInterval = 10;
    +		ExecutionConfig executionConfig = new ExecutionConfig();
    +		executionConfig.setAutoWatermarkInterval(watermarkInterval);
    +
    +		ContinuousFileReaderOperator<String, ?> reader = new ContinuousFileReaderOperator<>(format);
    +		reader.setOutputType(typeInfo, executionConfig);
    +
    +		final TestTimeServiceProvider timeServiceProvider = new TestTimeServiceProvider();
    +		final OneInputStreamOperatorTestHarness<FileInputSplit, String> tester =
    +			new OneInputStreamOperatorTestHarness<>(reader, executionConfig, timeServiceProvider);
    +		tester.setTimeCharacteristic(TimeCharacteristic.IngestionTime);
    +		tester.open();
    +
    +		Assert.assertEquals(TimeCharacteristic.IngestionTime, tester.getTimeCharacteristic());
    +
    +		// test that watermarks are correctly emitted
    +
    +		timeServiceProvider.setCurrentTime(201);
    +		timeServiceProvider.setCurrentTime(301);
    +		timeServiceProvider.setCurrentTime(401);
    +		timeServiceProvider.setCurrentTime(501);
    +
    +		int i = 0;
    +		for(Object line: tester.getOutput()) {
    +			if (!(line instanceof Watermark)) {
    +				Assert.fail("Only watermarks are expected here ");
    +			}
    +			Watermark w = (Watermark) line;
    +			Assert.assertEquals(200 + (i * 100), w.getTimestamp());
    +			i++;
    +		}
    +
    +		// clear the output to get the elements only and the final watermark
    +		tester.getOutput().clear();
    +		Assert.assertEquals(0, tester.getOutput().size());
    +
    +		// create the necessary splits for the test
    +		FileInputSplit[] splits = format.createInputSplits(
    +			reader.getRuntimeContext().getNumberOfParallelSubtasks());
    +
    +		// and feed them to the operator
    +		Map<Integer, List<String>> actualFileContents = new HashMap<>();
    +
    +		long lastSeenWatermark = Long.MIN_VALUE;
    +		int lineCounter = 0;	// counter for the lines read from the splits
    +		int watermarkCounter = 0;
    +
    +		for(FileInputSplit split: splits) {
    +
    +			// set the next "current processing time".
    +			long nextTimestamp = timeServiceProvider.getCurrentProcessingTime() + watermarkInterval;
    +			timeServiceProvider.setCurrentTime(nextTimestamp);
    +
    +			// send the next split to be read and wait until it is fully read.
    +			tester.processElement(new StreamRecord<>(split));
    +			synchronized (tester.getCheckpointLock()) {
    +				while (tester.getOutput().isEmpty() || tester.getOutput().size() != (LINES_PER_FILE + 1)) {
    +					tester.getCheckpointLock().wait(10);
    +				}
    +			}
    +
    +			// verify that the results are the expected
    +			for(Object line: tester.getOutput()) {
    +				if (line instanceof StreamRecord) {
    +					StreamRecord<String> element = (StreamRecord<String>) line;
    +					lineCounter++;
    +
    +					Assert.assertEquals(nextTimestamp, element.getTimestamp());
    +
    +					int fileIdx = Character.getNumericValue(element.getValue().charAt(0));
    +					List<String> content = actualFileContents.get(fileIdx);
    +					if (content == null) {
    +						content = new ArrayList<>();
    +						actualFileContents.put(fileIdx, content);
    +					}
    +					content.add(element.getValue() + "\n");
    +				} else if (line instanceof Watermark) {
    +					long watermark = ((Watermark) line).getTimestamp();
    +
    +					Assert.assertEquals(nextTimestamp - (nextTimestamp % watermarkInterval), watermark);
    +					Assert.assertTrue(watermark > lastSeenWatermark);
    +					watermarkCounter++;
    +
    +					lastSeenWatermark = watermark;
    +				} else {
    +					Assert.fail("Unknown element in the list.");
    +				}
    +			}
    +
    +			// clean the output to be ready for the next split
    +			tester.getOutput().clear();
    +		}
    +
    +		// now we are processing one split after the other,
    +		// so all the elements must be here by now.
    +		Assert.assertEquals(NO_OF_FILES * LINES_PER_FILE, lineCounter);
    +
    +		// because we expect one watermark per split.
    +		Assert.assertEquals(NO_OF_FILES, watermarkCounter);
    +
    +		// then close the reader gracefully so that the Long.MAX watermark is emitted
    +		synchronized (tester.getCheckpointLock()) {
    +			tester.close();
    +		}
    +
    +		for(org.apache.hadoop.fs.Path file: filesCreated) {
    +			hdfs.delete(file, false);
    +		}
    +
    +		// check if the last element is the LongMax watermark (by now this must be the only element)
    +		Assert.assertEquals(1, tester.getOutput().size());
    +		Assert.assertTrue(tester.getOutput().peek() instanceof Watermark);
    +		Assert.assertEquals(Long.MAX_VALUE, ((Watermark) tester.getOutput().poll()).getTimestamp());
    +
    +		// check if the elements are the expected ones.
    +		Assert.assertEquals(expectedFileContents.size(), actualFileContents.size());
    +		for (Integer fileIdx: expectedFileContents.keySet()) {
    +			Assert.assertTrue("file" + fileIdx + " not found", actualFileContents.keySet().contains(fileIdx));
    --- End diff --
    
    You wouldn't have to use file indexes if you immediately checked the split output.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #2593: [FLINK-4329] Fix Streaming File Source Timestamps/...

Posted by mxm <gi...@git.apache.org>.
Github user mxm commented on a diff in the pull request:

    https://github.com/apache/flink/pull/2593#discussion_r81944138
  
    --- Diff: flink-fs-tests/src/test/java/org/apache/flink/hdfstests/ContinuousFileMonitoringTest.java ---
    @@ -106,6 +107,155 @@ public static void destroyHDFS() {
     	//						TESTS
     
     	@Test
    +	public void testFileReadingOperatorWithIngestionTime() throws Exception {
    +		Set<org.apache.hadoop.fs.Path> filesCreated = new HashSet<>();
    +		Map<Integer, String> expectedFileContents = new HashMap<>();
    +
    +		for(int i = 0; i < NO_OF_FILES; i++) {
    +			Tuple2<org.apache.hadoop.fs.Path, String> file = fillWithData(hdfsURI, "file", i, "This is test line.");
    +			filesCreated.add(file.f0);
    +			expectedFileContents.put(i, file.f1);
    +		}
    +
    +		TextInputFormat format = new TextInputFormat(new Path(hdfsURI));
    +		TypeInformation<String> typeInfo = TypeExtractor.getInputFormatTypes(format);
    +
    +		final long watermarkInterval = 10;
    +		ExecutionConfig executionConfig = new ExecutionConfig();
    +		executionConfig.setAutoWatermarkInterval(watermarkInterval);
    +
    +		ContinuousFileReaderOperator<String, ?> reader = new ContinuousFileReaderOperator<>(format);
    +		reader.setOutputType(typeInfo, executionConfig);
    +
    +		final TestTimeServiceProvider timeServiceProvider = new TestTimeServiceProvider();
    +		final OneInputStreamOperatorTestHarness<FileInputSplit, String> tester =
    +			new OneInputStreamOperatorTestHarness<>(reader, executionConfig, timeServiceProvider);
    +		tester.setTimeCharacteristic(TimeCharacteristic.IngestionTime);
    +		tester.open();
    +
    +		Assert.assertEquals(TimeCharacteristic.IngestionTime, tester.getTimeCharacteristic());
    +
    +		// test that watermarks are correctly emitted
    +
    +		timeServiceProvider.setCurrentTime(201);
    +		timeServiceProvider.setCurrentTime(301);
    +		timeServiceProvider.setCurrentTime(401);
    +		timeServiceProvider.setCurrentTime(501);
    +
    +		int i = 0;
    +		for(Object line: tester.getOutput()) {
    +			if (!(line instanceof Watermark)) {
    +				Assert.fail("Only watermarks are expected here ");
    +			}
    +			Watermark w = (Watermark) line;
    +			Assert.assertEquals(200 + (i * 100), w.getTimestamp());
    +			i++;
    +		}
    +
    +		// clear the output to get the elements only and the final watermark
    +		tester.getOutput().clear();
    +		Assert.assertEquals(0, tester.getOutput().size());
    +
    +		// create the necessary splits for the test
    +		FileInputSplit[] splits = format.createInputSplits(
    +			reader.getRuntimeContext().getNumberOfParallelSubtasks());
    +
    +		// and feed them to the operator
    +		Map<Integer, List<String>> actualFileContents = new HashMap<>();
    +
    +		long lastSeenWatermark = Long.MIN_VALUE;
    +		int lineCounter = 0;	// counter for the lines read from the splits
    +		int watermarkCounter = 0;
    +
    +		for(FileInputSplit split: splits) {
    +
    +			// set the next "current processing time".
    +			long nextTimestamp = timeServiceProvider.getCurrentProcessingTime() + watermarkInterval;
    +			timeServiceProvider.setCurrentTime(nextTimestamp);
    +
    +			// send the next split to be read and wait until it is fully read.
    +			tester.processElement(new StreamRecord<>(split));
    +			synchronized (tester.getCheckpointLock()) {
    +				while (tester.getOutput().isEmpty() || tester.getOutput().size() != (LINES_PER_FILE + 1)) {
    +					tester.getCheckpointLock().wait(10);
    +				}
    +			}
    +
    +			// verify that the results are the expected
    +			for(Object line: tester.getOutput()) {
    --- End diff --
    
    Generally, I find
    
    ```java
    for (Object line : tester.getOutput()) {
    ```
    
    more readable.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #2593: [FLINK-4329] Fix Streaming File Source Timestamps/...

Posted by mxm <gi...@git.apache.org>.
Github user mxm commented on a diff in the pull request:

    https://github.com/apache/flink/pull/2593#discussion_r81946646
  
    --- Diff: flink-fs-tests/src/test/java/org/apache/flink/hdfstests/ContinuousFileMonitoringTest.java ---
    @@ -106,6 +107,155 @@ public static void destroyHDFS() {
     	//						TESTS
     
     	@Test
    +	public void testFileReadingOperatorWithIngestionTime() throws Exception {
    +		Set<org.apache.hadoop.fs.Path> filesCreated = new HashSet<>();
    +		Map<Integer, String> expectedFileContents = new HashMap<>();
    +
    +		for(int i = 0; i < NO_OF_FILES; i++) {
    +			Tuple2<org.apache.hadoop.fs.Path, String> file = fillWithData(hdfsURI, "file", i, "This is test line.");
    +			filesCreated.add(file.f0);
    +			expectedFileContents.put(i, file.f1);
    +		}
    +
    +		TextInputFormat format = new TextInputFormat(new Path(hdfsURI));
    +		TypeInformation<String> typeInfo = TypeExtractor.getInputFormatTypes(format);
    +
    +		final long watermarkInterval = 10;
    +		ExecutionConfig executionConfig = new ExecutionConfig();
    +		executionConfig.setAutoWatermarkInterval(watermarkInterval);
    +
    +		ContinuousFileReaderOperator<String, ?> reader = new ContinuousFileReaderOperator<>(format);
    +		reader.setOutputType(typeInfo, executionConfig);
    +
    +		final TestTimeServiceProvider timeServiceProvider = new TestTimeServiceProvider();
    +		final OneInputStreamOperatorTestHarness<FileInputSplit, String> tester =
    +			new OneInputStreamOperatorTestHarness<>(reader, executionConfig, timeServiceProvider);
    +		tester.setTimeCharacteristic(TimeCharacteristic.IngestionTime);
    +		tester.open();
    +
    +		Assert.assertEquals(TimeCharacteristic.IngestionTime, tester.getTimeCharacteristic());
    +
    +		// test that watermarks are correctly emitted
    +
    +		timeServiceProvider.setCurrentTime(201);
    +		timeServiceProvider.setCurrentTime(301);
    +		timeServiceProvider.setCurrentTime(401);
    +		timeServiceProvider.setCurrentTime(501);
    +
    +		int i = 0;
    +		for(Object line: tester.getOutput()) {
    +			if (!(line instanceof Watermark)) {
    +				Assert.fail("Only watermarks are expected here ");
    +			}
    +			Watermark w = (Watermark) line;
    +			Assert.assertEquals(200 + (i * 100), w.getTimestamp());
    +			i++;
    +		}
    +
    +		// clear the output to get the elements only and the final watermark
    +		tester.getOutput().clear();
    +		Assert.assertEquals(0, tester.getOutput().size());
    +
    +		// create the necessary splits for the test
    +		FileInputSplit[] splits = format.createInputSplits(
    +			reader.getRuntimeContext().getNumberOfParallelSubtasks());
    +
    +		// and feed them to the operator
    +		Map<Integer, List<String>> actualFileContents = new HashMap<>();
    +
    +		long lastSeenWatermark = Long.MIN_VALUE;
    +		int lineCounter = 0;	// counter for the lines read from the splits
    +		int watermarkCounter = 0;
    +
    +		for(FileInputSplit split: splits) {
    +
    +			// set the next "current processing time".
    +			long nextTimestamp = timeServiceProvider.getCurrentProcessingTime() + watermarkInterval;
    +			timeServiceProvider.setCurrentTime(nextTimestamp);
    +
    +			// send the next split to be read and wait until it is fully read.
    +			tester.processElement(new StreamRecord<>(split));
    +			synchronized (tester.getCheckpointLock()) {
    +				while (tester.getOutput().isEmpty() || tester.getOutput().size() != (LINES_PER_FILE + 1)) {
    +					tester.getCheckpointLock().wait(10);
    --- End diff --
    
    Actually, sleeping wouldn't be necessary if you disabled the threaded split processing of the `SplitReader` for this test. You could have a synchronous reader for the test (would require a small change of the operator/reader to enable that).


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #2593: [FLINK-4329] Fix Streaming File Source Timestamps/...

Posted by mxm <gi...@git.apache.org>.
Github user mxm commented on a diff in the pull request:

    https://github.com/apache/flink/pull/2593#discussion_r82004204
  
    --- Diff: flink-streaming-java/src/main/java/org/apache/flink/streaming/api/operators/StreamSource.java ---
    @@ -214,14 +216,24 @@ public AutomaticWatermarkContext(
     			this.watermarkInterval = watermarkInterval;
     			this.reuse = new StreamRecord<T>(null);
     
    +			// if it is a source, then we cast and cache it
    +			// here so that we do not have to do it in every collect(),
    +			// collectWithTimestamp() and emitWatermark()
    +
    +			if (!(owner instanceof AsyncExceptionChecker)) {
    +				throw new IllegalStateException("The ManualWatermarkContext can only be used " +
    --- End diff --
    
    AutomaticWatermarkContext?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #2593: [FLINK-4329] Fix Streaming File Source Timestamps/...

Posted by mxm <gi...@git.apache.org>.
Github user mxm commented on a diff in the pull request:

    https://github.com/apache/flink/pull/2593#discussion_r81945670
  
    --- Diff: flink-fs-tests/src/test/java/org/apache/flink/hdfstests/ContinuousFileMonitoringTest.java ---
    @@ -106,6 +107,155 @@ public static void destroyHDFS() {
     	//						TESTS
     
     	@Test
    +	public void testFileReadingOperatorWithIngestionTime() throws Exception {
    +		Set<org.apache.hadoop.fs.Path> filesCreated = new HashSet<>();
    +		Map<Integer, String> expectedFileContents = new HashMap<>();
    +
    +		for(int i = 0; i < NO_OF_FILES; i++) {
    +			Tuple2<org.apache.hadoop.fs.Path, String> file = fillWithData(hdfsURI, "file", i, "This is test line.");
    +			filesCreated.add(file.f0);
    +			expectedFileContents.put(i, file.f1);
    +		}
    +
    +		TextInputFormat format = new TextInputFormat(new Path(hdfsURI));
    +		TypeInformation<String> typeInfo = TypeExtractor.getInputFormatTypes(format);
    +
    +		final long watermarkInterval = 10;
    +		ExecutionConfig executionConfig = new ExecutionConfig();
    +		executionConfig.setAutoWatermarkInterval(watermarkInterval);
    +
    +		ContinuousFileReaderOperator<String, ?> reader = new ContinuousFileReaderOperator<>(format);
    +		reader.setOutputType(typeInfo, executionConfig);
    +
    +		final TestTimeServiceProvider timeServiceProvider = new TestTimeServiceProvider();
    +		final OneInputStreamOperatorTestHarness<FileInputSplit, String> tester =
    +			new OneInputStreamOperatorTestHarness<>(reader, executionConfig, timeServiceProvider);
    +		tester.setTimeCharacteristic(TimeCharacteristic.IngestionTime);
    +		tester.open();
    +
    +		Assert.assertEquals(TimeCharacteristic.IngestionTime, tester.getTimeCharacteristic());
    +
    +		// test that watermarks are correctly emitted
    +
    +		timeServiceProvider.setCurrentTime(201);
    +		timeServiceProvider.setCurrentTime(301);
    +		timeServiceProvider.setCurrentTime(401);
    +		timeServiceProvider.setCurrentTime(501);
    +
    +		int i = 0;
    +		for(Object line: tester.getOutput()) {
    +			if (!(line instanceof Watermark)) {
    +				Assert.fail("Only watermarks are expected here ");
    +			}
    +			Watermark w = (Watermark) line;
    +			Assert.assertEquals(200 + (i * 100), w.getTimestamp());
    +			i++;
    --- End diff --
    
    I think this can be more easily readable if you break it up into:
    
    ```java
    timeServiceProvider.setCurrentTime(201);
    Assert.assertEquals(200, ((Watermark) tester.getOutput().poll()).getTimestamp());
    // ....
    ```


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #2593: [FLINK-4329] Fix Streaming File Source Timestamps/...

Posted by mxm <gi...@git.apache.org>.
Github user mxm commented on a diff in the pull request:

    https://github.com/apache/flink/pull/2593#discussion_r81944268
  
    --- Diff: flink-fs-tests/src/test/java/org/apache/flink/hdfstests/ContinuousFileMonitoringTest.java ---
    @@ -106,6 +107,155 @@ public static void destroyHDFS() {
     	//						TESTS
     
     	@Test
    +	public void testFileReadingOperatorWithIngestionTime() throws Exception {
    +		Set<org.apache.hadoop.fs.Path> filesCreated = new HashSet<>();
    +		Map<Integer, String> expectedFileContents = new HashMap<>();
    +
    +		for(int i = 0; i < NO_OF_FILES; i++) {
    +			Tuple2<org.apache.hadoop.fs.Path, String> file = fillWithData(hdfsURI, "file", i, "This is test line.");
    +			filesCreated.add(file.f0);
    +			expectedFileContents.put(i, file.f1);
    +		}
    +
    +		TextInputFormat format = new TextInputFormat(new Path(hdfsURI));
    +		TypeInformation<String> typeInfo = TypeExtractor.getInputFormatTypes(format);
    +
    +		final long watermarkInterval = 10;
    +		ExecutionConfig executionConfig = new ExecutionConfig();
    +		executionConfig.setAutoWatermarkInterval(watermarkInterval);
    +
    +		ContinuousFileReaderOperator<String, ?> reader = new ContinuousFileReaderOperator<>(format);
    +		reader.setOutputType(typeInfo, executionConfig);
    +
    +		final TestTimeServiceProvider timeServiceProvider = new TestTimeServiceProvider();
    +		final OneInputStreamOperatorTestHarness<FileInputSplit, String> tester =
    +			new OneInputStreamOperatorTestHarness<>(reader, executionConfig, timeServiceProvider);
    +		tester.setTimeCharacteristic(TimeCharacteristic.IngestionTime);
    +		tester.open();
    +
    +		Assert.assertEquals(TimeCharacteristic.IngestionTime, tester.getTimeCharacteristic());
    +
    +		// test that watermarks are correctly emitted
    +
    +		timeServiceProvider.setCurrentTime(201);
    +		timeServiceProvider.setCurrentTime(301);
    +		timeServiceProvider.setCurrentTime(401);
    +		timeServiceProvider.setCurrentTime(501);
    +
    +		int i = 0;
    +		for(Object line: tester.getOutput()) {
    +			if (!(line instanceof Watermark)) {
    +				Assert.fail("Only watermarks are expected here ");
    +			}
    +			Watermark w = (Watermark) line;
    +			Assert.assertEquals(200 + (i * 100), w.getTimestamp());
    +			i++;
    +		}
    +
    +		// clear the output to get the elements only and the final watermark
    +		tester.getOutput().clear();
    +		Assert.assertEquals(0, tester.getOutput().size());
    +
    +		// create the necessary splits for the test
    +		FileInputSplit[] splits = format.createInputSplits(
    +			reader.getRuntimeContext().getNumberOfParallelSubtasks());
    +
    +		// and feed them to the operator
    +		Map<Integer, List<String>> actualFileContents = new HashMap<>();
    +
    +		long lastSeenWatermark = Long.MIN_VALUE;
    +		int lineCounter = 0;	// counter for the lines read from the splits
    +		int watermarkCounter = 0;
    +
    +		for(FileInputSplit split: splits) {
    +
    +			// set the next "current processing time".
    +			long nextTimestamp = timeServiceProvider.getCurrentProcessingTime() + watermarkInterval;
    +			timeServiceProvider.setCurrentTime(nextTimestamp);
    +
    +			// send the next split to be read and wait until it is fully read.
    +			tester.processElement(new StreamRecord<>(split));
    +			synchronized (tester.getCheckpointLock()) {
    +				while (tester.getOutput().isEmpty() || tester.getOutput().size() != (LINES_PER_FILE + 1)) {
    +					tester.getCheckpointLock().wait(10);
    +				}
    +			}
    +
    +			// verify that the results are the expected
    +			for(Object line: tester.getOutput()) {
    +				if (line instanceof StreamRecord) {
    +					StreamRecord<String> element = (StreamRecord<String>) line;
    +					lineCounter++;
    +
    +					Assert.assertEquals(nextTimestamp, element.getTimestamp());
    +
    +					int fileIdx = Character.getNumericValue(element.getValue().charAt(0));
    +					List<String> content = actualFileContents.get(fileIdx);
    +					if (content == null) {
    +						content = new ArrayList<>();
    +						actualFileContents.put(fileIdx, content);
    +					}
    +					content.add(element.getValue() + "\n");
    +				} else if (line instanceof Watermark) {
    +					long watermark = ((Watermark) line).getTimestamp();
    +
    +					Assert.assertEquals(nextTimestamp - (nextTimestamp % watermarkInterval), watermark);
    +					Assert.assertTrue(watermark > lastSeenWatermark);
    +					watermarkCounter++;
    +
    +					lastSeenWatermark = watermark;
    +				} else {
    +					Assert.fail("Unknown element in the list.");
    +				}
    +			}
    +
    +			// clean the output to be ready for the next split
    +			tester.getOutput().clear();
    +		}
    +
    +		// now we are processing one split after the other,
    +		// so all the elements must be here by now.
    +		Assert.assertEquals(NO_OF_FILES * LINES_PER_FILE, lineCounter);
    +
    +		// because we expect one watermark per split.
    +		Assert.assertEquals(NO_OF_FILES, watermarkCounter);
    --- End diff --
    
    This should be `Assert.assertEquals(splits.length, watermarkCounter);`.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #2593: [FLINK-4329] Fix Streaming File Source Timestamps/...

Posted by mxm <gi...@git.apache.org>.
Github user mxm commented on a diff in the pull request:

    https://github.com/apache/flink/pull/2593#discussion_r81944208
  
    --- Diff: flink-fs-tests/src/test/java/org/apache/flink/hdfstests/ContinuousFileMonitoringTest.java ---
    @@ -106,6 +107,155 @@ public static void destroyHDFS() {
     	//						TESTS
     
     	@Test
    +	public void testFileReadingOperatorWithIngestionTime() throws Exception {
    +		Set<org.apache.hadoop.fs.Path> filesCreated = new HashSet<>();
    +		Map<Integer, String> expectedFileContents = new HashMap<>();
    +
    +		for(int i = 0; i < NO_OF_FILES; i++) {
    +			Tuple2<org.apache.hadoop.fs.Path, String> file = fillWithData(hdfsURI, "file", i, "This is test line.");
    +			filesCreated.add(file.f0);
    +			expectedFileContents.put(i, file.f1);
    +		}
    +
    +		TextInputFormat format = new TextInputFormat(new Path(hdfsURI));
    +		TypeInformation<String> typeInfo = TypeExtractor.getInputFormatTypes(format);
    +
    +		final long watermarkInterval = 10;
    +		ExecutionConfig executionConfig = new ExecutionConfig();
    +		executionConfig.setAutoWatermarkInterval(watermarkInterval);
    +
    +		ContinuousFileReaderOperator<String, ?> reader = new ContinuousFileReaderOperator<>(format);
    +		reader.setOutputType(typeInfo, executionConfig);
    +
    +		final TestTimeServiceProvider timeServiceProvider = new TestTimeServiceProvider();
    +		final OneInputStreamOperatorTestHarness<FileInputSplit, String> tester =
    +			new OneInputStreamOperatorTestHarness<>(reader, executionConfig, timeServiceProvider);
    +		tester.setTimeCharacteristic(TimeCharacteristic.IngestionTime);
    +		tester.open();
    +
    +		Assert.assertEquals(TimeCharacteristic.IngestionTime, tester.getTimeCharacteristic());
    +
    +		// test that watermarks are correctly emitted
    +
    +		timeServiceProvider.setCurrentTime(201);
    +		timeServiceProvider.setCurrentTime(301);
    +		timeServiceProvider.setCurrentTime(401);
    +		timeServiceProvider.setCurrentTime(501);
    +
    +		int i = 0;
    +		for(Object line: tester.getOutput()) {
    +			if (!(line instanceof Watermark)) {
    +				Assert.fail("Only watermarks are expected here ");
    +			}
    +			Watermark w = (Watermark) line;
    +			Assert.assertEquals(200 + (i * 100), w.getTimestamp());
    +			i++;
    +		}
    +
    +		// clear the output to get the elements only and the final watermark
    +		tester.getOutput().clear();
    +		Assert.assertEquals(0, tester.getOutput().size());
    +
    +		// create the necessary splits for the test
    +		FileInputSplit[] splits = format.createInputSplits(
    +			reader.getRuntimeContext().getNumberOfParallelSubtasks());
    +
    +		// and feed them to the operator
    +		Map<Integer, List<String>> actualFileContents = new HashMap<>();
    +
    +		long lastSeenWatermark = Long.MIN_VALUE;
    +		int lineCounter = 0;	// counter for the lines read from the splits
    +		int watermarkCounter = 0;
    +
    +		for(FileInputSplit split: splits) {
    +
    +			// set the next "current processing time".
    +			long nextTimestamp = timeServiceProvider.getCurrentProcessingTime() + watermarkInterval;
    +			timeServiceProvider.setCurrentTime(nextTimestamp);
    +
    +			// send the next split to be read and wait until it is fully read.
    +			tester.processElement(new StreamRecord<>(split));
    +			synchronized (tester.getCheckpointLock()) {
    +				while (tester.getOutput().isEmpty() || tester.getOutput().size() != (LINES_PER_FILE + 1)) {
    +					tester.getCheckpointLock().wait(10);
    +				}
    +			}
    +
    +			// verify that the results are the expected
    +			for(Object line: tester.getOutput()) {
    +				if (line instanceof StreamRecord) {
    +					StreamRecord<String> element = (StreamRecord<String>) line;
    --- End diff --
    
    You could add a `@SupressWarnings("unchecked");` here.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #2593: [FLINK-4329] Fix Streaming File Source Timestamps/...

Posted by mxm <gi...@git.apache.org>.
Github user mxm commented on a diff in the pull request:

    https://github.com/apache/flink/pull/2593#discussion_r81944479
  
    --- Diff: flink-fs-tests/src/test/java/org/apache/flink/hdfstests/ContinuousFileMonitoringTest.java ---
    @@ -106,6 +107,155 @@ public static void destroyHDFS() {
     	//						TESTS
     
     	@Test
    +	public void testFileReadingOperatorWithIngestionTime() throws Exception {
    +		Set<org.apache.hadoop.fs.Path> filesCreated = new HashSet<>();
    +		Map<Integer, String> expectedFileContents = new HashMap<>();
    +
    +		for(int i = 0; i < NO_OF_FILES; i++) {
    +			Tuple2<org.apache.hadoop.fs.Path, String> file = fillWithData(hdfsURI, "file", i, "This is test line.");
    +			filesCreated.add(file.f0);
    +			expectedFileContents.put(i, file.f1);
    +		}
    +
    +		TextInputFormat format = new TextInputFormat(new Path(hdfsURI));
    +		TypeInformation<String> typeInfo = TypeExtractor.getInputFormatTypes(format);
    +
    +		final long watermarkInterval = 10;
    +		ExecutionConfig executionConfig = new ExecutionConfig();
    +		executionConfig.setAutoWatermarkInterval(watermarkInterval);
    +
    +		ContinuousFileReaderOperator<String, ?> reader = new ContinuousFileReaderOperator<>(format);
    +		reader.setOutputType(typeInfo, executionConfig);
    +
    +		final TestTimeServiceProvider timeServiceProvider = new TestTimeServiceProvider();
    +		final OneInputStreamOperatorTestHarness<FileInputSplit, String> tester =
    +			new OneInputStreamOperatorTestHarness<>(reader, executionConfig, timeServiceProvider);
    +		tester.setTimeCharacteristic(TimeCharacteristic.IngestionTime);
    +		tester.open();
    +
    +		Assert.assertEquals(TimeCharacteristic.IngestionTime, tester.getTimeCharacteristic());
    +
    +		// test that watermarks are correctly emitted
    +
    +		timeServiceProvider.setCurrentTime(201);
    +		timeServiceProvider.setCurrentTime(301);
    +		timeServiceProvider.setCurrentTime(401);
    +		timeServiceProvider.setCurrentTime(501);
    +
    +		int i = 0;
    +		for(Object line: tester.getOutput()) {
    +			if (!(line instanceof Watermark)) {
    +				Assert.fail("Only watermarks are expected here ");
    +			}
    +			Watermark w = (Watermark) line;
    +			Assert.assertEquals(200 + (i * 100), w.getTimestamp());
    +			i++;
    +		}
    +
    +		// clear the output to get the elements only and the final watermark
    +		tester.getOutput().clear();
    +		Assert.assertEquals(0, tester.getOutput().size());
    +
    +		// create the necessary splits for the test
    +		FileInputSplit[] splits = format.createInputSplits(
    +			reader.getRuntimeContext().getNumberOfParallelSubtasks());
    +
    +		// and feed them to the operator
    +		Map<Integer, List<String>> actualFileContents = new HashMap<>();
    +
    +		long lastSeenWatermark = Long.MIN_VALUE;
    +		int lineCounter = 0;	// counter for the lines read from the splits
    +		int watermarkCounter = 0;
    +
    +		for(FileInputSplit split: splits) {
    +
    +			// set the next "current processing time".
    +			long nextTimestamp = timeServiceProvider.getCurrentProcessingTime() + watermarkInterval;
    +			timeServiceProvider.setCurrentTime(nextTimestamp);
    +
    +			// send the next split to be read and wait until it is fully read.
    +			tester.processElement(new StreamRecord<>(split));
    +			synchronized (tester.getCheckpointLock()) {
    +				while (tester.getOutput().isEmpty() || tester.getOutput().size() != (LINES_PER_FILE + 1)) {
    +					tester.getCheckpointLock().wait(10);
    +				}
    +			}
    +
    +			// verify that the results are the expected
    +			for(Object line: tester.getOutput()) {
    +				if (line instanceof StreamRecord) {
    +					StreamRecord<String> element = (StreamRecord<String>) line;
    +					lineCounter++;
    +
    +					Assert.assertEquals(nextTimestamp, element.getTimestamp());
    +
    +					int fileIdx = Character.getNumericValue(element.getValue().charAt(0));
    +					List<String> content = actualFileContents.get(fileIdx);
    +					if (content == null) {
    +						content = new ArrayList<>();
    +						actualFileContents.put(fileIdx, content);
    +					}
    +					content.add(element.getValue() + "\n");
    +				} else if (line instanceof Watermark) {
    +					long watermark = ((Watermark) line).getTimestamp();
    +
    +					Assert.assertEquals(nextTimestamp - (nextTimestamp % watermarkInterval), watermark);
    +					Assert.assertTrue(watermark > lastSeenWatermark);
    +					watermarkCounter++;
    +
    +					lastSeenWatermark = watermark;
    +				} else {
    +					Assert.fail("Unknown element in the list.");
    +				}
    +			}
    +
    +			// clean the output to be ready for the next split
    +			tester.getOutput().clear();
    +		}
    +
    +		// now we are processing one split after the other,
    +		// so all the elements must be here by now.
    +		Assert.assertEquals(NO_OF_FILES * LINES_PER_FILE, lineCounter);
    +
    +		// because we expect one watermark per split.
    +		Assert.assertEquals(NO_OF_FILES, watermarkCounter);
    +
    +		// then close the reader gracefully so that the Long.MAX watermark is emitted
    +		synchronized (tester.getCheckpointLock()) {
    +			tester.close();
    +		}
    +
    +		for(org.apache.hadoop.fs.Path file: filesCreated) {
    +			hdfs.delete(file, false);
    +		}
    +
    +		// check if the last element is the LongMax watermark (by now this must be the only element)
    +		Assert.assertEquals(1, tester.getOutput().size());
    +		Assert.assertTrue(tester.getOutput().peek() instanceof Watermark);
    +		Assert.assertEquals(Long.MAX_VALUE, ((Watermark) tester.getOutput().poll()).getTimestamp());
    +
    +		// check if the elements are the expected ones.
    +		Assert.assertEquals(expectedFileContents.size(), actualFileContents.size());
    +		for (Integer fileIdx: expectedFileContents.keySet()) {
    +			Assert.assertTrue("file" + fileIdx + " not found", actualFileContents.keySet().contains(fileIdx));
    +
    +			List<String> cntnt = actualFileContents.get(fileIdx);
    +			Collections.sort(cntnt, new Comparator<String>() {
    --- End diff --
    
    Sorting here wouldn't be necessary if you immediately compared the output of the split after reading it.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #2593: [FLINK-4329] Fix Streaming File Source Timestamps/...

Posted by StephanEwen <gi...@git.apache.org>.
Github user StephanEwen commented on a diff in the pull request:

    https://github.com/apache/flink/pull/2593#discussion_r81990874
  
    --- Diff: flink-streaming-java/src/main/java/org/apache/flink/streaming/api/operators/StreamSource.java ---
    @@ -214,14 +216,26 @@ public AutomaticWatermarkContext(
     			this.watermarkInterval = watermarkInterval;
     			this.reuse = new StreamRecord<T>(null);
     
    +			// if it is a source, then we cast and cache it
    +			// here so that we do not have to do it in every collect(),
    +			// collectWithTimestamp() and emitWatermark()
    +
    +			if (!(owner instanceof AsyncExceptionChecker)) {
    +				throw new IllegalStateException("The ManualWatermarkContext can only be used " +
    +					"with sources that implement the AsyncExceptionChecker interface.");
    +			}
    +			this.source = (AsyncExceptionChecker) owner;
    +
     			long now = owner.getCurrentProcessingTime();
     			this.watermarkTimer = owner.registerTimer(now + watermarkInterval,
     				new WatermarkEmittingTask(owner, lockingObjectParam, outputParam));
     		}
     
     		@Override
     		public void collect(T element) {
    -			owner.checkAsyncException();
    +			if (source != null) {
    --- End diff --
    
    source can never be null?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] flink pull request #2593: [FLINK-4329] Fix Streaming File Source Timestamps/...

Posted by StephanEwen <gi...@git.apache.org>.
Github user StephanEwen commented on a diff in the pull request:

    https://github.com/apache/flink/pull/2593#discussion_r81990910
  
    --- Diff: flink-streaming-java/src/main/java/org/apache/flink/streaming/api/operators/StreamSource.java ---
    @@ -250,7 +264,9 @@ public void collectWithTimestamp(T element, long timestamp) {
     
     		@Override
     		public void emitWatermark(Watermark mark) {
    -			owner.checkAsyncException();
    +			if (source != null) {
    --- End diff --
    
    same here


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---