Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Fixed
-
0.10.0, 0.9.3
Description
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 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(); } } }
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.