You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@nifi.apache.org by "Serhii Nesterov (Jira)" <ji...@apache.org> on 2023/08/21 11:07:00 UTC

[jira] [Comment Edited] (NIFI-11971) FlowFile content is corrupted across the whole NiFi instance throughout ProcessSession::write with omitting writing any byte to OutputStream

    [ https://issues.apache.org/jira/browse/NIFI-11971?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17756795#comment-17756795 ] 

Serhii Nesterov edited comment on NIFI-11971 at 8/21/23 11:06 AM:
------------------------------------------------------------------

[~markap14] Thanks for the quick response. I was also wondering if this fix will take effect if any exception is raised between creation of a new content claim and creation of an output stream. There two try-catch clauses - the claim is created in the first one, the output stream is created in the second one. If any exception is thrown in the first clause, then I assume that the output stream in the second clause will not be reached (falls down to the catch section, skipping the second try-catch), will not be created, hence the close method will not be invoked to recompute the current content claim length ({*}-1{*} to {*}0{*}), and the next _session.write()_ may lead to the same issue. What do you think?

!image-2023-08-21-13-21-31-091.png!


was (Author: JIRAUSER298214):
[~markap14] Thanks for the quick response. I was also wondering if this fix will take effect if any exception is raised between creation of a new content claim and creation of an output stream. There two try-catch clauses - the claim is created in the first one, the output stream in created in the second one. If any exception is thrown in the first clause, then I assume that the output stream in the second clause will not be reached (falles down to the catch section, skipping the second try-catch), will not be created, hence the close method will not be invoked to recompute the current content claim length ({*}-1{*} to {*}0{*}), and the next _session.write()_ may lead to the same issue. What do you think?

!image-2023-08-21-13-21-31-091.png!

> FlowFile content is corrupted across the whole NiFi instance throughout ProcessSession::write with omitting writing any byte to OutputStream
> --------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: NIFI-11971
>                 URL: https://issues.apache.org/jira/browse/NIFI-11971
>             Project: Apache NiFi
>          Issue Type: Bug
>          Components: Core Framework
>    Affects Versions: 1.23.0, 1.23.1
>            Reporter: Serhii Nesterov
>            Assignee: Mark Payne
>            Priority: Blocker
>              Labels: corruption
>             Fix For: 1.24.0
>
>         Attachments: image-2023-08-20-19-31-16-598.png, image-2023-08-20-19-37-43-772.png, image-2023-08-20-19-38-03-391.png, image-2023-08-20-19-42-37-029.png, image-2023-08-20-19-43-03-697.png, image-2023-08-20-20-01-50-445.png, image-2023-08-21-13-21-31-091.png
>
>          Time Spent: 10m
>  Remaining Estimate: 0h
>
> One of the scenarios for ProcessSession::write was broken after recent code refactoring within the following pull request: [https://github.com/apache/nifi/pull/7363/files]
> The issue is located in _StandardContentClaimWriteCache.java_ in the _write(final ContentClaim claim)_ method that returns an _OutputStream_ used in the _OutputStreamCallback_ interface to let NiFi processors write flowfile content through the {_}ProcessSession::write method{_}.
> If a processor calls _session.write_ but does not write any data to the output stream, then none of the write methods in the _OutputStream_ is invoked, hence the length of the content claim is not recomputed, meaning the length will have the default value that is equal to {*}-1{*}. Because of the latest refactoring changes that are based on creating a new content claim on each _ProcessSession::write_ invocation the following formula gives the wrong result:
> {code:java}
> previous offset + previous length = new offset.{code}
> or as in the codebase:
> {code:java}
> scc = new StandardContentClaim(scc.getResourceClaim(), scc.getOffset() + scc.getLength());{code}
> For example, if the previous offset was 1000 and nothing was written to the stream (length is -1), then 1000 + (-1) will give us 999 which means that the offset is shifted back by one, hence the next content will have an extra character from the previous content at the beginning and will lose the last character at the end, and all other FlowFiles anywhere in NiFi will be corrupted by this defect until the NiFi instance is restarted.
> The following steps can be taken to reproduce the issue (critical in our commercial project):
>  * Create an empty text file (“a.txt”);
>  * Create a text file with any text (“b.txt”);
>  * Package these files into a .zip archive;
>  * Put it into a file system on Azure Cloud (we use ADLS Gen2);
>  * Read the zip file and unpack its content on the NiFi Canvas using the _FetchAzureDataLakeStorage_ and _UnpackContent_ processors;
>  * Start a flow with the _GenerateFlowFile_ processor. See the results. The empty file must be extracted before the non-empty file, otherwise the issue won’t reproduce. You’ll see that the second FlowFile content will be corrupted – the first character is an unreadable character from the zip archive (last character of the content with zip) fetched with _FetchAzureDataLakeStorage_ and the last character will be lost. Starting from this point, NiFi cannot be used at all because any other processors will lead to FlowFile content corruption across the entire NiFi instance due to the shifted offset.
> A sample canvas:
> !image-2023-08-20-19-31-16-598.png|width=969,height=492!
>  
> Important note: the issue is not reproducible if an empty file is a last file to be extracted (the length will be reset when the processor completes), or if you do not call _session.write()_ when a file has 0 bytes (in case if you create your own processor with such logic).
> The offsets for the above picture will look like as follows (#1 - after fetching and unpacking an empty file, #2 - before unpacking the second file):  !image-2023-08-20-19-37-43-772.png|width=961,height=32!
> !image-2023-08-20-19-38-03-391.png|width=960,height=35!
> 1524 - after FetchAzureDataLakeStorage and UnpackContent for the empty file. The length *-1* will be kept instead of *0* and used for the next file which is why the next offset is equal to 1523 ({*}1524 + (-1) = 1523{*}).
> if your file has the "Hello world" text inside, then after downloading this unpacked file from NiFi you'll see (the first character here is a space):
> !image-2023-08-20-20-01-50-445.png!
> Different processors will give you various errors due to the corrupted content especially for the json format and queries:
> !image-2023-08-20-19-42-37-029.png!
> !image-2023-08-20-19-43-03-697.png!



--
This message was sent by Atlassian Jira
(v8.20.10#820010)