Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Persist dump file content for dynamic simulation #116

Merged
merged 15 commits into from
Nov 18, 2024
Merged

Conversation

thangqp
Copy link
Contributor

@thangqp thangqp commented Oct 28, 2024

  • Dump file exported by dynamic simulation is persisted in db in order to reuse as one of inputs for dynamic security analysis

@thangqp thangqp changed the title Export dump file for dynamic simulation Persist dump file content for dynamic simulation Oct 30, 2024
@thangqp thangqp requested a review from ghazwarhili November 13, 2024 09:57
try (InputStream is = Files.newInputStream(filePath);
ByteArrayOutputStream os = new ByteArrayOutputStream()) {
// Important: zipOs must be outside of try to call manually close() in order to add EOF to os
ZipOutputStream zipOs = new ZipOutputStream(os);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can use the zipOs whithin the try with resource block to avoid the call of close() manually ? as it will be closed automatically by the try block finishes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DONE in 85a0baa

zipOs.write(buffer, 0, length);
}
// call close() manually to add EOF to os
zipOs.close();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can call the closeEntry() to finalize the entry which is more explicit

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

YES

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DONE in 85a0baa

zipOs.close();
return os.toByteArray();
} catch (IOException e) {
throw new UncheckedIOException(e);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add message to improve debugging if an error occurs

Suggested change
throw new UncheckedIOException(e);
throw new UncheckedIOException("Failed to zip the provided file", e);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DONE in 85a0baa

}
}
} catch (IOException e) {
throw new UncheckedIOException(e);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the same here

Suggested change
throw new UncheckedIOException(e);
throw new UncheckedIOException("Failed to unzip the provided byte array", e);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DONE in 85a0baa

while ((length = zipIs.read(buffer)) > 0) {
fos.write(buffer, 0, length);
}
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you need to close properly the entry
zipIs.closeEntry()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

YES

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DONE in 85a0baa

runContext.setWorkDir(workDir);

} catch (IOException e) {
throw new UncheckedIOException(e);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
throw new UncheckedIOException(e);
throw new UncheckedIOException("Error creating temporary working directory for dynamo simulation", e);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DONE in 85a0baa

Path dumpDir = workDir.resolve("dump");
FileUtil.createDirectory(dumpDir);
DynawoSimulationParameters dynawoSimulationParameters = parameters.getExtension(DynawoSimulationParameters.class);
dynawoSimulationParameters.setDumpFileParameters(DumpFileParameters.createExportDumpFileParameters(dumpDir));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parameters.getExtension(...) could return null ?
you can use optional.ofNullable(...) to make it safer otherwise throw exception

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The extension is created in the previous step https://github.com/gridsuite/dynamic-simulation-server/blob/main/src/main/java/org/gridsuite/ds/server/service/parameters/impl/ParametersServiceImpl.java#L109, so it is never null.

Otherwise, throw another exception is not better than NPE, anyway the program must be stopped, the difference is instead of returning to end user a technical exception, we return a functional exception.

}
}

updateResult(resultContext.getResultUuid(), result, outputState);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move and extract this logic from saveResult into small helper methods to reduce the complexity of the new code

  1. Path dumpDir = getDumpFilePath(resultContext);
  2. byte[] outputState = null; and if (dumpDir != null) { outputState = zipDumpFile(dumpDir); }
  3. updateResult(resultContext.getResultUuid(), result, outputState);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DONE in 85a0baa


// check dump file not empty
byte[] outputState = dynamicSimulationResultService.getOutputState(runUuid);
assertThat(outputState).isNotEmpty();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assertThat(outputState).isNotEmpty();
assertThat(outputState)
.withFailMessage("Output state for the dynamo simulation is empty ...")
.isNotEmpty();

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DONE in 85a0baa

// check dump file not empty
byte[] outputState = dynamicSimulationResultService.getOutputState(runUuid);
assertThat(outputState).isNotEmpty();
logger.info("Size of zipped output state = {} KB ", outputState.length / 1024);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you sure about the logging level ?
shouldn't be logging in debug level here ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is test code, I prefer to show important info in any mode to facilitate analysis

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NO ACTION

Copy link

@ghazwarhili ghazwarhili left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code => OK
Test => OK

@@ -84,4 +90,38 @@ public static Property convertProperty(BasicProperty property) {

return propertyBuilder.build();
}

public static byte[] zip(Path filePath) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gzip would be more appropriated for the compression of one file

Copy link
Contributor Author

@thangqp thangqp Nov 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DONE in f295c86

@@ -46,4 +47,7 @@ public ResultEntity(UUID id, UUID timeSeriesId, UUID timeLineId, DynamicSimulati
@Enumerated(EnumType.STRING)
private DynamicSimulationStatus status;

@Column(name = "outputState")
private byte[] outputState;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a problem to have the file content in the same entity and same table. See dynamicSimulationService.findStatus(). You request the whole file just to get the computation status

Copy link
Contributor Author

@thangqp thangqp Nov 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A solution is using projection for select and and jpql for update lay avoid loading outputState in memory.
DONE in 87f095b

@thangqp thangqp merged commit 38af3d8 into main Nov 18, 2024
3 checks passed
@thangqp thangqp deleted the ds_export_dump_file branch November 18, 2024 13:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants