Omaha #3130 Fix thread safety issue in NetCDFFile.
Change-Id: I99999c827507a565e1980fe2b686cef4d848fe7d Former-commit-id:68a0c42242
[formerly47bdee2a58
[formerly 36f4c0f9b339dc91577cb231e2804d83f4f52706]] Former-commit-id:47bdee2a58
Former-commit-id:bc7e037504
This commit is contained in:
parent
d6611b5e32
commit
0f4df01d71
1 changed files with 85 additions and 115 deletions
|
@ -25,7 +25,9 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import ucar.ma2.ArrayChar;
|
||||
import ucar.ma2.ArrayFloat;
|
||||
|
@ -54,7 +56,9 @@ import com.raytheon.uf.common.time.TimeRange;
|
|||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* May 14, 2012 randerso Initial creation
|
||||
* May 14, 2012 randerso Initial creation
|
||||
* Jun 04, 2014 #3130 randerso Fix thread safety issues with NetcdfFile variable.
|
||||
* General code cleanup
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -83,8 +87,6 @@ public class NetCDFFile {
|
|||
|
||||
private List<String> levelNames;
|
||||
|
||||
// private long possibleInventoryBits;
|
||||
|
||||
public ParmAtts() {
|
||||
maxVal = 0;
|
||||
minVal = 0;
|
||||
|
@ -238,15 +240,13 @@ public class NetCDFFile {
|
|||
|
||||
private String fname;
|
||||
|
||||
private NetcdfFile cdf;
|
||||
|
||||
private Date modelTime;
|
||||
|
||||
private String modelName;
|
||||
|
||||
private List<TimeRange> availableTimes;
|
||||
|
||||
private List<ParmAtts> atts;
|
||||
private Map<String, ParmAtts> atts;
|
||||
|
||||
private ProjectionData projection;
|
||||
|
||||
|
@ -268,24 +268,34 @@ public class NetCDFFile {
|
|||
public NetCDFFile(String fname, String overrideModelName) {
|
||||
this.valid = false;
|
||||
this.fname = fname;
|
||||
this.cdf = null;
|
||||
|
||||
// NcError nce(NcError::silent_nonfatal);
|
||||
|
||||
CHECK_STATE(setModelTime());
|
||||
CHECK_STATE(openCDF());
|
||||
if (overrideModelName == null || overrideModelName.length() > 0) {
|
||||
this.modelName = overrideModelName;
|
||||
} else {
|
||||
CHECK_STATE(getModel());
|
||||
NetcdfFile cdf = null;
|
||||
try {
|
||||
cdf = NetcdfFile.open(this.fname);
|
||||
if ((overrideModelName == null) || (overrideModelName.length() > 0)) {
|
||||
this.modelName = overrideModelName;
|
||||
} else {
|
||||
CHECK_STATE(getModel(cdf));
|
||||
}
|
||||
CHECK_STATE(getProj(cdf));
|
||||
CHECK_STATE(getTimes(cdf));
|
||||
getTPDurations(cdf);
|
||||
CHECK_STATE(getNames(cdf));
|
||||
this.valid = true;
|
||||
} catch (IOException e) {
|
||||
statusHandler.error("Error opening NetCDF file: " + fname, e);
|
||||
} finally {
|
||||
if (cdf != null) {
|
||||
try {
|
||||
cdf.close();
|
||||
} catch (IOException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Error closing netCDF file " + this.fname + ": "
|
||||
+ e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
CHECK_STATE(getProj());
|
||||
CHECK_STATE(getTimes());
|
||||
getTPDurations();
|
||||
CHECK_STATE(getNames());
|
||||
|
||||
closeCDF();
|
||||
this.valid = true;
|
||||
}
|
||||
|
||||
private void CHECK_STATE(ServerResponse<?> sr) {
|
||||
|
@ -315,10 +325,6 @@ public class NetCDFFile {
|
|||
return availableTimes;
|
||||
}
|
||||
|
||||
public List<ParmAtts> getAtts() {
|
||||
return atts;
|
||||
}
|
||||
|
||||
public ProjectionData getProjection() {
|
||||
return projection;
|
||||
}
|
||||
|
@ -337,7 +343,7 @@ public class NetCDFFile {
|
|||
private ServerResponse<Float> getFloatVarAtt(Variable var, String name) {
|
||||
ServerResponse<Float> sr = new ServerResponse<Float>();
|
||||
Attribute att = var.findAttribute(name);
|
||||
if (att == null || !att.getDataType().equals(DataType.FLOAT)) {
|
||||
if ((att == null) || !att.getDataType().equals(DataType.FLOAT)) {
|
||||
sr.addMessage("Missing or invalid attribute: " + name);
|
||||
return sr;
|
||||
}
|
||||
|
@ -361,7 +367,7 @@ public class NetCDFFile {
|
|||
private ServerResponse<String> getStringVarAtt(Variable var, String name) {
|
||||
ServerResponse<String> sr = new ServerResponse<String>();
|
||||
Attribute att = var.findAttribute(name);
|
||||
if (att == null || !att.getDataType().equals(DataType.STRING)) {
|
||||
if ((att == null) || !att.getDataType().equals(DataType.STRING)) {
|
||||
sr.addMessage("Missing or invalid attribute: " + name);
|
||||
return sr;
|
||||
}
|
||||
|
@ -371,8 +377,8 @@ public class NetCDFFile {
|
|||
return sr;
|
||||
}
|
||||
|
||||
private ServerResponse<ProjectionData> getProj() {
|
||||
ServerResponse<ProjectionData> sr = NetCDFUtils.getProj(this.cdf);
|
||||
private ServerResponse<ProjectionData> getProj(NetcdfFile cdf) {
|
||||
ServerResponse<ProjectionData> sr = NetCDFUtils.getProj(cdf);
|
||||
if (sr.isOkay()) {
|
||||
this.projection = sr.getPayload();
|
||||
}
|
||||
|
@ -383,10 +389,7 @@ public class NetCDFFile {
|
|||
* @return a list of parm names found in this netCDF file.
|
||||
*/
|
||||
public List<String> getParmNames() {
|
||||
List<String> rval = new ArrayList<String>(this.atts.size());
|
||||
for (int i = 0; i < atts.size(); i++) {
|
||||
rval.add(atts.get(i).getName());
|
||||
}
|
||||
List<String> rval = new ArrayList<String>(this.atts.keySet());
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
@ -421,7 +424,7 @@ public class NetCDFFile {
|
|||
* @param var
|
||||
* @return
|
||||
*/
|
||||
private ServerResponse<ParmAtts> getParmAtts(Variable var) {
|
||||
private ServerResponse<ParmAtts> getParmAtts(NetcdfFile cdf, Variable var) {
|
||||
ServerResponse<ParmAtts> sr = new ServerResponse<ParmAtts>();
|
||||
|
||||
String units, longname;
|
||||
|
@ -450,7 +453,7 @@ public class NetCDFFile {
|
|||
|
||||
if (!tsrmin.isOkay() || !tsrmax.isOkay()) {
|
||||
Attribute att = var.findAttribute("valid_range");
|
||||
if (att != null && att.getLength() == 2
|
||||
if ((att != null) && (att.getLength() == 2)
|
||||
&& att.getDataType().equals(DataType.FLOAT)) {
|
||||
min = att.getNumericValue(0).floatValue();
|
||||
max = att.getNumericValue(1).floatValue();
|
||||
|
@ -528,7 +531,7 @@ public class NetCDFFile {
|
|||
// Y coordinate = time, X coordinate = levels
|
||||
for (int y = 0; y < dims[0]; y++) {
|
||||
for (int x = 0; x < idims[1]; x++) {
|
||||
char c = (char) dta.getByte(y * idims[1] + x);
|
||||
char c = (char) dta.getByte((y * idims[1]) + x);
|
||||
byte b = (byte) (c == '1' ? 1 : 0);
|
||||
inventory.set(x, y, b);
|
||||
}
|
||||
|
@ -582,11 +585,13 @@ public class NetCDFFile {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
private ServerResponse<Object> getNames() {
|
||||
private ServerResponse<Object> getNames(NetcdfFile cdf) {
|
||||
ServerResponse<Object> sr = new ServerResponse<Object>();
|
||||
|
||||
this.atts = new ArrayList<NetCDFFile.ParmAtts>();
|
||||
for (Variable var : this.cdf.getVariables()) {
|
||||
List<Variable> variables = cdf.getVariables();
|
||||
this.atts = new HashMap<String, NetCDFFile.ParmAtts>(variables.size(),
|
||||
1.0f);
|
||||
for (Variable var : variables) {
|
||||
if (var != null) {
|
||||
if (!var.getDataType().equals(DataType.FLOAT)) {
|
||||
continue;
|
||||
|
@ -614,10 +619,11 @@ public class NetCDFFile {
|
|||
}
|
||||
}
|
||||
if (foundx && foundy) {
|
||||
ServerResponse<ParmAtts> tsr = getParmAtts(var);
|
||||
ServerResponse<ParmAtts> tsr = getParmAtts(cdf, var);
|
||||
sr.addMessages(tsr);
|
||||
if (tsr.isOkay()) {
|
||||
this.atts.add(tsr.getPayload());
|
||||
ParmAtts parmAtts = tsr.getPayload();
|
||||
this.atts.put(parmAtts.getName(), parmAtts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -631,7 +637,7 @@ public class NetCDFFile {
|
|||
* model files.
|
||||
*
|
||||
*/
|
||||
private void getTPDurations() {
|
||||
private void getTPDurations(NetcdfFile cdf) {
|
||||
this.tpSubPrev = new ArrayList<Boolean>(getAvailableTimes().size());
|
||||
for (int i = 0; i < getAvailableTimes().size(); i++) {
|
||||
this.tpSubPrev.add(false);
|
||||
|
@ -640,8 +646,8 @@ public class NetCDFFile {
|
|||
long duration = (getAvailableTimes().get(1).getStart().getTime() - getAvailableTimes()
|
||||
.get(0).getStart().getTime()) / 1000;
|
||||
String s = String.format("_tp%d", (duration / 3600) * 2);
|
||||
Variable tvar = this.cdf.findVariable(s);
|
||||
if (tvar != null && tvar.getDataType().equals(DataType.FLOAT)) {
|
||||
Variable tvar = cdf.findVariable(s);
|
||||
if ((tvar != null) && tvar.getDataType().equals(DataType.FLOAT)) {
|
||||
Dimension d1 = tvar.getDimension(0);
|
||||
if (d1 != null) {
|
||||
try {
|
||||
|
@ -665,10 +671,10 @@ public class NetCDFFile {
|
|||
*
|
||||
* @return ServerResponse
|
||||
*/
|
||||
private ServerResponse<Object> getTimes() {
|
||||
private ServerResponse<Object> getTimes(NetcdfFile cdf) {
|
||||
ServerResponse<Object> sr = new ServerResponse<Object>();
|
||||
Variable tvar = this.cdf.findVariable("valtimeMINUSreftime");
|
||||
if (tvar == null || !tvar.getDataType().equals(DataType.INT)) {
|
||||
Variable tvar = cdf.findVariable("valtimeMINUSreftime");
|
||||
if ((tvar == null) || !tvar.getDataType().equals(DataType.INT)) {
|
||||
sr.addMessage("Missing or invalid 'valtimeMINUSreftime' var.");
|
||||
} else {
|
||||
Dimension d1 = tvar.getDimension(0);
|
||||
|
@ -681,8 +687,9 @@ public class NetCDFFile {
|
|||
d1.getLength());
|
||||
for (int i = 0; i < d1.getLength(); i++) {
|
||||
this.availableTimes.add(new TimeRange(new Date(
|
||||
this.modelTime.getTime() + times.getInt(i)
|
||||
* 1000L), 3600 * 1000));
|
||||
this.modelTime.getTime()
|
||||
+ (times.getInt(i) * 1000L)),
|
||||
3600 * 1000));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
statusHandler.handle(
|
||||
|
@ -702,10 +709,10 @@ public class NetCDFFile {
|
|||
*
|
||||
* @return ServerResponse
|
||||
*/
|
||||
private ServerResponse<Object> getModel() {
|
||||
private ServerResponse<Object> getModel(NetcdfFile cdf) {
|
||||
ServerResponse<Object> sr = new ServerResponse<Object>();
|
||||
Variable mvar = this.cdf.findVariable("model");
|
||||
if (mvar == null || !mvar.getDataType().equals(DataType.CHAR)) {
|
||||
Variable mvar = cdf.findVariable("model");
|
||||
if ((mvar == null) || !mvar.getDataType().equals(DataType.CHAR)) {
|
||||
sr.addMessage("Missing or invalid 'model' var.");
|
||||
} else {
|
||||
try {
|
||||
|
@ -720,40 +727,6 @@ public class NetCDFFile {
|
|||
return sr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to open the netcdf file. If it can not be opened (or is not a
|
||||
* valid cdf file) then an invalid ServerResponse is returned.
|
||||
*
|
||||
* @return ServerResponse
|
||||
*/
|
||||
private ServerResponse<Object> openCDF() {
|
||||
ServerResponse<Object> sr = new ServerResponse<Object>();
|
||||
try {
|
||||
this.cdf = NetcdfFile.open(this.fname);
|
||||
if (this.cdf == null) {
|
||||
sr.addMessage("Invalid NetCDF file: " + this.fname);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, "Error opening netCDF file "
|
||||
+ this.fname + ": " + e.getLocalizedMessage(), e);
|
||||
}
|
||||
return sr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the netcdf file.
|
||||
*
|
||||
*/
|
||||
private void closeCDF() {
|
||||
try {
|
||||
this.cdf.close();
|
||||
} catch (IOException e) {
|
||||
statusHandler.handle(Priority.PROBLEM, "Error closing netCDF file "
|
||||
+ this.fname + ": " + e.getLocalizedMessage(), e);
|
||||
}
|
||||
this.cdf = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to determine the models run time. If it fails, an invalid
|
||||
* ServerResponse will be returned.
|
||||
|
@ -774,51 +747,48 @@ public class NetCDFFile {
|
|||
* @return the ParmAtts
|
||||
*/
|
||||
public ParmAtts getAtts(String parmName) {
|
||||
for (ParmAtts a : this.atts) {
|
||||
if (a.getName().equals(parmName)) {
|
||||
return a;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return this.atts.get(parmName);
|
||||
}
|
||||
|
||||
public Grid2DFloat getGrid(String parmName, int index, int level,
|
||||
Rectangle subdomain) {
|
||||
ParmAtts atts = getAtts(parmName);
|
||||
if (atts == null) {
|
||||
if (!this.atts.containsKey(parmName)) {
|
||||
statusHandler.handle(Priority.PROBLEM, "Unknown parm name: "
|
||||
+ parmName);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!openCDF().isOkay()) {
|
||||
statusHandler.handle(Priority.PROBLEM, "Error opening CDF File: "
|
||||
+ this.fname);
|
||||
this.valid = false;
|
||||
return null;
|
||||
}
|
||||
NetcdfFile cdf = null;
|
||||
try {
|
||||
cdf = NetcdfFile.open(this.fname);
|
||||
|
||||
for (ParmAtts a : this.atts) {
|
||||
if (parmName.equals(a.getName())) {
|
||||
Grid2DFloat grid = null;
|
||||
ServerResponse<Grid2DFloat> sr = NetCDFUtils.getFloatGrid(
|
||||
this.cdf, parmName, index, level, subdomain);
|
||||
if (!sr.isOkay()) {
|
||||
closeCDF();
|
||||
statusHandler.handle(Priority.PROBLEM, sr.message());
|
||||
return null;
|
||||
} else {
|
||||
grid = sr.getPayload();
|
||||
Grid2DFloat grid = null;
|
||||
ServerResponse<Grid2DFloat> sr = NetCDFUtils.getFloatGrid(cdf,
|
||||
parmName, index, level, subdomain);
|
||||
if (!sr.isOkay()) {
|
||||
statusHandler.handle(Priority.PROBLEM, sr.message());
|
||||
return null;
|
||||
} else {
|
||||
grid = sr.getPayload();
|
||||
}
|
||||
|
||||
return grid;
|
||||
} catch (IOException e) {
|
||||
statusHandler.error("Error opening NetCDF file: " + fname, e);
|
||||
} finally {
|
||||
if (cdf != null) {
|
||||
try {
|
||||
cdf.close();
|
||||
} catch (IOException e) {
|
||||
statusHandler.handle(Priority.PROBLEM,
|
||||
"Error closing netCDF file " + this.fname + ": "
|
||||
+ e.getLocalizedMessage(), e);
|
||||
}
|
||||
|
||||
closeCDF();
|
||||
return grid;
|
||||
}
|
||||
}
|
||||
|
||||
statusHandler
|
||||
.handle(Priority.PROBLEM, "unknown parm name: " + parmName);
|
||||
closeCDF();
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue