Xiangdong Huang created IOTDB-735:
-------------------------------------
Summary: Concurrent error for MNode when creating time series
automatically
Key: IOTDB-735
URL: https://issues.apache.org/jira/browse/IOTDB-735
Project: Apache IoTDB
Issue Type: Bug
Components: Core/Engine
Affects Versions: 0.9.3, 0.10.0-SNAPSHOT
Reporter: Xiangdong Huang
When multiply users write time series data concurrently and IoTDB enables
auto_create_timeseries, sometimes NullpointException may be thrown from
PlanExecutor.
The NullPointer exception is thrown from `LeafMNode measurementNode =
(LeafMNode) node.getChild(measurement);`.
{code:java}
// code placeholder
@Override
public void insert(InsertPlan insertPlan) throws QueryProcessException {
MNode node = null;
try {
String[] measurementList = insertPlan.getMeasurements();
String deviceId = insertPlan.getDeviceId();
node = mManager.getDeviceNodeWithAutoCreateAndReadLock(deviceId);
MeasurementSchema[] schemas = new MeasurementSchema[measurementList.length];
for (int i = 0; i < measurementList.length; i++) {
String measurement = measurementList[i];
if (!node.hasChild(measurement)) {
if
(!IoTDBDescriptor.getInstance().getConfig().isAutoCreateSchemaEnabled()) {
throw new PathNotExistException(deviceId + PATH_SEPARATOR +
measurement);
}
TSDataType dataType = TypeInferenceUtils
.getPredictedDataType(insertPlan.getValues()[i],
insertPlan.isInferType());
Path path = new Path(deviceId, measurement);
internalCreateTimeseries(path.toString(), dataType);
}
LeafMNode measurementNode = (LeafMNode) node.getChild(measurement);
schemas[i] = measurementNode.getSchema();
// reset measurement to common name instead of alias
measurementList[i] = measurementNode.getName();
if(!insertPlan.isInferType()) {
checkType(insertPlan, i, measurementNode.getSchema().getType());
}
}
insertPlan.setMeasurements(measurementList);
insertPlan.setSchemasAndTransferType(schemas);
StorageEngine.getInstance().insert(insertPlan);
} catch (StorageEngineException | MetadataException e) {
throw new QueryProcessException(e);
} finally {
if (node != null) {
((InternalMNode) node).readUnlock();
}
}
}
{code}
The reason is, this method operates MNode instance directly without mtree.lock.
Then, when `node.getChild()` is called, someone may call `node.addChild()` and
the Concurrent error may lead the `node.getChild()` returns null.
So, be careful when you directly operate a MNode instance.
--
This message was sent by Atlassian Jira
(v8.3.4#803005)