forked from Unidata/netcdf-java
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNetcdfClibrary.java
More file actions
195 lines (170 loc) · 6.17 KB
/
Copy pathNetcdfClibrary.java
File metadata and controls
195 lines (170 loc) · 6.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/*
* Copyright (c) 1998-2021 John Caron and University Corporation for Atmospheric Research/Unidata
* See LICENSE for license information.
*/
package ucar.nc2.ffi.netcdf;
import com.google.common.base.Strings;
import com.sun.jna.Library;
import com.sun.jna.Native;
import java.lang.reflect.Proxy;
import javax.annotation.Nullable;
import ucar.nc2.jni.netcdf.Nc4prototypes;
import ucar.nc2.jni.netcdf.Nc4wrapper;
/** Static methods to load the netcdf C library. */
public class NetcdfClibrary {
private static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(NetcdfClibrary.class);
private static final String JNA_PATH = "jna.library.path";
private static final String JNA_PATH_ENV = "JNA_PATH"; // environment var
private static final String JNA_LOG_LEVEL = "jna.library.loglevel";
private static String DEFAULT_NETCDF4_LIBNAME = "netcdf";
private static String jnaPath;
private static String libName = DEFAULT_NETCDF4_LIBNAME;
private static Nc4prototypes nc4;
private static int log_level;
private static String version;
// Track if already tested for library presence.
private static Boolean isClibraryPresent;
/**
* Set the path and name of the netcdf c library.
* <p>
* Must be called prior to calling {@link #isLibraryPresent() isLibraryPresent}
* or {@link #getForeignFunctionInterface() getForeignFunctionInterface}, as
* the C library can only be successfully loaded once.
*
* @param jna_path path to shared libraries, may be null. If null, will look for system property
* "jna.library.path", then environment variable "JNA_PATH". If set, will set
* the environment variable "JNA_PATH".
* @param lib_name library name, may be null. If null, will use "netcdf".
*/
public static void setLibraryNameAndPath(@Nullable String jna_path, @Nullable String lib_name) {
if (nc4 != null) {
log.warn("netCDF-C library already set, ignoring.");
return;
}
lib_name = Strings.emptyToNull(lib_name);
if (lib_name == null) {
lib_name = DEFAULT_NETCDF4_LIBNAME;
}
jna_path = Strings.emptyToNull(jna_path);
if (jna_path == null) {
jna_path = Strings.emptyToNull(System.getProperty(JNA_PATH)); // First, try system property (-D flag).
}
if (jna_path == null) {
jna_path = Strings.emptyToNull(System.getenv(JNA_PATH_ENV)); // Next, try environment variable.
}
if (jna_path != null) {
System.setProperty(JNA_PATH, jna_path);
}
libName = lib_name;
jnaPath = jna_path;
if ((isClibraryPresent == null || !isClibraryPresent) && jnaPath != null) {
// call load to retry loading, but this time with jnaPath set
load();
}
}
/**
* Test if the netcdf C library is present and loaded
*
* @return true if present
*/
public static synchronized boolean isLibraryPresent() {
if (isClibraryPresent == null) {
isClibraryPresent = load() != null;
}
return isClibraryPresent;
}
/** Get the interface to the Nectdf C library. */
public static synchronized Nc4prototypes getForeignFunctionInterface() {
return isLibraryPresent() ? nc4 : null;
}
/** Get the version of the loaded Nectdf C library. Call isClibraryPresent() first. */
@Nullable
public static String getVersion() {
if (nc4 != null && version == null) {
try {
version = nc4.nc_inq_libvers();
} catch (UnsatisfiedLinkError e) {
// ignore
}
}
return version;
}
/**
* Set the log level for Netcdf C library.
* This calls the Netcdf C library nc_set_log_level() method.
* If the system property "jna.library.loglevel" is set, that is the default, this method overrides it.
*
* @return the previous level, as returned from nc_set_log_level().
*/
public static synchronized int setLogLevel(int level) {
int oldlevel = -1;
log_level = level;
if (nc4 != null) {
try {
oldlevel = nc4.nc_set_log_level(log_level);
log.info(String.format("NetcdfLoader: set log level: old=%d new=%d", oldlevel, log_level));
} catch (UnsatisfiedLinkError e) {
// ignore
}
}
return oldlevel;
}
/**
* Closes the netCDF-C native library.
*
* <p>
* Call this method to ensure JNA can shut down its cleaner thread; otherwise JVM shutdown may be blocked.
* </p>
*/
public static synchronized void shutdown() {
if (nc4 != null) {
Library.Handler lh = (Library.Handler) Proxy.getInvocationHandler(nc4);
lh.getNativeLibrary().close();
nc4 = null;
}
}
private static Nc4prototypes load() {
if (nc4 == null) {
if (jnaPath == null) {
setLibraryNameAndPath(null, null);
}
try {
// jna_path may still be null, but try to load anyway;
// the necessary libs may be on the system PATH or on LD_LIBRARY_PATH
nc4 = Native.load(libName, Nc4prototypes.class);
// Make the library synchronized
// nc4 = (Nc4prototypes) Native.synchronizedLibrary(nc4);
nc4 = new Nc4wrapper(nc4);
log.info("Nc4Iosp: NetCDF-4 C library loaded (jna_path='{}', libname='{}' version='{}').", jnaPath, libName,
getVersion());
log.debug("Netcdf nc_inq_libvers='{}' isProtected={}", nc4.nc_inq_libvers(), Native.isProtected());
} catch (Throwable t) {
String message =
String.format("Nc4Iosp: NetCDF-4 C library not present (jna_path='%s', libname='%s').", jnaPath, libName);
log.warn(message);
log.debug("details: ", t);
}
String slevel = Strings.emptyToNull(System.getProperty(JNA_LOG_LEVEL));
if (slevel != null) {
try {
log_level = Integer.parseInt(slevel);
} catch (NumberFormatException nfe) {
// no change
}
}
try {
setLogLevel(log_level);
} catch (Throwable t) {
String message = String.format("Nc4Iosp: could not set log level (level=%d jna_path='%s', libname='%s').",
log_level, jnaPath, libName);
log.debug("Nc4Iosp: " + t.getMessage());
}
}
return nc4;
}
//////////////////////////////////////////////////
// Do not construct
private NetcdfClibrary() {
throw new UnsupportedOperationException();
}
}