Uploaded image for project: 'Apache IoTDB'
  1. Apache IoTDB
  2. IOTDB-735

Concurrent error for MNode when creating time series automatically

    XMLWordPrintableJSON

Details

    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.

       

       

       

       

       

      Attachments

        Activity

          People

            Unassigned Unassigned
            hxd Xiangdong Huang
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: