Uploaded image for project: 'Ignite'
  1. Ignite
  2. IGNITE-15396

TableManager#table(UUID) could return null value even though the required table is already created

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Major
    • Resolution: Fixed
    • None
    • 3.0.0-alpha4
    • None

    Description

      It seems that the following code introduced by IGNITE-14970 can lead to an error if a required table already exists in the cluster but the current node has not seen this event:

      if (tbl != null && getTblFut.complete(tbl) || getTblFut.complete(null))
          removeListener(TableEvent.CREATE, clo, null);
      

       

      https://github.com/apache/ignite-3/blob/main/modules/table/src/main/java/org/apache/ignite/internal/table/distributed/TableManager.java#L832

      Looks like it should be something as follows:

      if (tbl != null && getTblFut.complete(tbl) || 
          !isTableConfigured(id) && getTblFut.complete(null))
          removeListener(TableEvent.CREATE, clo, null);
      

       UPD 1

       Besides mention above it's also required to check whether table is present in meta storage, instead of just checking it locally

      As-Is:

      var tbl = tablesById.get(id);
      
      if (tbl != null)
          return tbl;
      

      To-Be:

      if (!tableIdsConfigured().values().contains(id))
          return null;
          
      var tbl = tablesById.get(id);
      
      if (tbl != null)
          return tbl;
      

      However proper retrieval of distributed state is not implemented yet IGNITE-15412

      There's a hack solution

          private Map</* table name*/String, /* table id*/IgniteUuid> tableCoordinatesConfigured() {
              IgniteBiTuple<ByteArray, ByteArray> range = toRange(new ByteArray(PUBLIC_PREFIX));        var tableCoordinates = new HashMap<String, IgniteUuid>();
              String tblName = null;
              String innerTblId = null;        try (Cursor<Entry> cursor = metaStorageMgr.range(range.get1(), range.get2())) {
                  while (cursor.hasNext()) {
                      Entry entry = cursor.next();                List<String> keySplit = ConfigurationUtil.split(entry.key().toString());                if (keySplit.size() == 5 && NamedListNode.NAME.equals(keySplit.get(4))) {
                          @Nullable byte[] value = entry.value();
                          if (value != null) {
                              tblName = ByteUtils.fromBytes(value).toString();
                              innerTblId = keySplit.get(3);
                          }
                      }                if (keySplit.size() == 5 && "id".equals(keySplit.get(4)) && keySplit.get(3).equals(innerTblId))
                          tableCoordinates.put(tblName, IgniteUuid.fromString(ByteUtils.fromBytes(entry.value()).toString()));
                  }
              }
              catch (Exception e) {
                  LOG.error("Can't get table names.", e);
              }        return tableCoordinates;
          }
      
      

      However it's extremely horrible, so we'd better wait for IGNITE-15412

       

      Attachments

        Issue Links

          Activity

            People

              v.pyatkov Vladislav Pyatkov
              slava.koptilin Vyacheslav Koptilin
              Alexander Lapin Alexander Lapin
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Time Tracking

                  Estimated:
                  Original Estimate - Not Specified
                  Not Specified
                  Remaining:
                  Remaining Estimate - 0h
                  0h
                  Logged:
                  Time Spent - 8h 10m
                  8h 10m