[m-rev.] for review use the Java library file copying methods
Julien Fischer
jfischer at opturion.com
Mon Jan 8 16:50:30 AEDT 2024
For review by anyone.
This doesn't appear to be any faster (on Linux); the main advantage is
removing the dependency on "cp".
------------------------------------
Use the Java library file copying methods.
Use the file copy methods from the Java library when the compiler is built
in the Java grades.
compiler/copy_util.m:
Add a copy method that use the Files.copy() from the Java library.
Simplify the interface to the Windows file copying functionality.
Julien.
diff --git a/compiler/copy_util.m b/compiler/copy_util.m
index cf3bad9..f1134dd 100644
--- a/compiler/copy_util.m
+++ b/compiler/copy_util.m
@@ -49,7 +49,7 @@
% - We also support copying using mechanisms provided by the underlying
% platform, which we expect may be faster than just using pure Mercury
% code. We access those mechanisms via foreign_procs. This is currently
-% only done for C grades on Windows.
+% only done for C grades on Windows and for the Java grade.
%
% Regardless of the mechanism, we must ensure that copying preserves
% as much of the file's metadata as possible. Notably, this must include
@@ -112,6 +112,8 @@
:- import_module bool.
:- import_module dir.
:- import_module int.
+:- import_module io.error_util.
+:- import_module maybe.
:- import_module require. % Required by non-C grades.
:- import_module string.
@@ -183,15 +185,22 @@ do_copy_file(SourceFile, DestinationFile, Res, !IO) :-
;
CopyMethod = icm_windows_api,
windows_copy_file(SourceFile, DestinationFile, Res, !IO)
+ ;
+ CopyMethod = icm_java_library,
+ java_copy_file(SourceFile, DestinationFile, Res, !IO)
).
:- type internal_copy_method
- ---> icm_mercury_impl % Mercury copy implementation.
- ; icm_windows_api. % CopyFileW() function from the Windows API.
+ ---> icm_mercury_impl % Mercury copy implementation.
+ ; icm_windows_api % CopyFileW() function from the Windows API.
+ ; icm_java_library. % Files.copy() from the Java library.
:- pragma foreign_export_enum("C", internal_copy_method/0,
[prefix("MC_"), uppercase]).
+:- pragma foreign_export_enum("Java", internal_copy_method/0,
+ [prefix("MC_"), uppercase]).
+
:- func get_internal_copy_method = internal_copy_method.
:- pragma foreign_proc("C",
@@ -203,10 +212,16 @@ do_copy_file(SourceFile, DestinationFile, Res, !IO) :-
#else
Method = MC_ICM_MERCURY_IMPL;
#endif
+").
+:- pragma foreign_proc("Java",
+ get_internal_copy_method = (Method::out),
+ [will_not_call_mercury, thread_safe, promise_pure],
+"
+ Method = MC_ICM_JAVA_LIBRARY;
").
-% For the non-C backends.
+% For the C# backend.
get_internal_copy_method = icm_mercury_impl.
%-----------------------------------------------------------------------------%
@@ -218,15 +233,14 @@ get_internal_copy_method = icm_mercury_impl.
io::di, io::uo) is det.
windows_copy_file(Source, Destination, Res, !IO) :-
- do_windows_copy_file(Source, Destination, IsOk, SysErr, !IO),
+ do_windows_copy_file(Source, Destination, SysErr, !IO),
+ is_error_maybe_win32(SysErr, yes, "file copy failed: ", MaybeIOError, !IO),
(
- IsOk = yes,
- Res = ok
- ;
- IsOk = no,
- io.make_io_error_from_windows_error(SysErr, "file copy failed: ",
- IO_Error, !IO),
+ MaybeIOError = yes(IO_Error),
Res = error(IO_Error)
+ ;
+ MaybeIOError = no,
+ Res = ok
).
:- pragma foreign_decl("C", "
@@ -237,22 +251,18 @@ windows_copy_file(Source, Destination, Res, !IO) :-
#endif
").
-
:- pred do_windows_copy_file(file_name::in, file_name::in, bool::out,
system_error::out, io::di, io::uo) is det.
:- pragma no_determinism_warning(pred(do_windows_copy_file/6)).
:- pragma foreign_proc("C",
- do_windows_copy_file(Src::in, Dst::in, IsOk::out, SysErr::out,
- _IO0::di, _IO::uo),
+ do_windows_copy_file(Src::in, Dst::in, SysErr::out, _IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, thread_safe, tabled_for_io],
"
#if defined(MR_WIN32)
if (CopyFileW(MR_utf8_to_wide(Src), MR_utf8_to_wide(Dst), FALSE)) {
- IsOk = MR_YES;
SysErr = 0;
} else {
- IsOk = MR_NO;
SysErr = GetLastError();
}
#else
@@ -260,9 +270,52 @@ windows_copy_file(Source, Destination, Res, !IO) :-
#endif
").
-do_windows_copy_file(_, _, _, _, _, _) :-
+do_windows_copy_file(_, _, _, _, _) :-
unexpected($pred,
- "do_windows_copy_file/6 not supported on non-C backends").
+ "do_windows_copy_file/5 not supported on non-C backends").
+
+%-----------------------------------------------------------------------------%
+%
+% File copying using the Java library.
+%
+
+:- pred java_copy_file(file_name::in, file_name::in, io.res::out,
+ io::di, io::uo) is det.
+
+java_copy_file(Source, Destination, Res, !IO) :-
+ do_java_copy_file(Source, Destination, SysErr, !IO),
+ is_error(SysErr, "file copy failed: ", MaybeIOError, !IO),
+ (
+ MaybeIOError = yes(IO_Error),
+ Res = error(IO_Error)
+ ;
+ MaybeIOError = no,
+ Res = ok
+ ).
+
+:- pred do_java_copy_file(file_name::in, file_name::in, system_error::out,
+ io::di, io::uo) is det.
+:- pragma no_determinism_warning(pred(do_java_copy_file/5)).
+
+:- pragma foreign_proc("Java",
+ do_java_copy_file(Src::in, Dst::in, Error::out, _IO0::di, _IO::uo),
+ [will_not_call_mercury, promise_pure, thread_safe],
+"
+ try {
+ java.nio.file.Files.copy(
+ java.nio.file.Paths.get(Src),
+ java.nio.file.Paths.get(Dst),
+ java.nio.file.StandardCopyOption.REPLACE_EXISTING,
+ java.nio.file.StandardCopyOption.COPY_ATTRIBUTES);
+ Error = null;
+ } catch (java.lang.Exception e) {
+ Error = e;
+ }
+").
+
+do_java_copy_file(_, _, _, _, _) :-
+ unexpected($pred,
+ "do_java_copy_file/5 not supported on non-Java backends").
%-----------------------------------------------------------------------------%
%
More information about the reviews
mailing list