private void compareRecords()

in core/src/main/java/com/jetbrains/youtrackdb/internal/core/db/tool/DatabaseCompare.java [654:864]


  private void compareRecords(EntityHelper.RIDMapper ridMapper) {
    listener.onMessage(
        "\nStarting deep comparison record by record. This may take a few minutes. Wait please...");

    var collectionNames1 = sessionOne.getCollectionNames();

    for (final var collectionName : collectionNames1) {
      // CHECK IF THE COLLECTION IS INCLUDED
      final var collectionId1 = sessionOne.getCollectionIdByName(collectionName);
      RecordIdInternal rid1 = null;

      var physicalPositions = sessionOne.getStorage()
          .ceilingPhysicalPositions(sessionOne, collectionId1, new PhysicalPosition(0),
              Integer.MAX_VALUE);

      var configuration1 = sessionOne.getStorageInfo().getConfiguration();
      var configuration2 = sessionTwo.getStorageInfo().getConfiguration();

      var storageType1 = sessionOne.getStorage().getType();
      var storageType2 = sessionTwo.getStorage().getType();

      long recordsCounter = 0;
      while (physicalPositions.length > 0) {
        for (var physicalPosition : physicalPositions) {
          try {
            recordsCounter++;

            final var entity1 = new EntityImpl(sessionOne,
                new RecordId(RID.COLLECTION_ID_INVALID, RID.COLLECTION_POS_INVALID));
            final var entity2 = new EntityImpl(sessionTwo,
                new RecordId(RID.COLLECTION_ID_INVALID, RID.COLLECTION_POS_INVALID));

            final var position = physicalPosition.collectionPosition;
            rid1 = new RecordId(collectionId1, position);

            final RecordIdInternal rid2;
            if (ridMapper == null) {
              rid2 = rid1;
            } else {
              final var newRid = ridMapper.map(rid1);
              if (newRid == null) {
                rid2 = rid1;
              } else
              //noinspection ObjectAllocationInLoop
              {
                rid2 = new RecordId(newRid);
              }
            }

            if (skipRecord(
                rid1, rid2, configuration1, configuration2, storageType1, storageType2)) {
              continue;
            }

            final var buffer1 = sessionOne.getStorage().readRecord(rid1);
            final var buffer2 = sessionTwo.getStorage().readRecord(rid2);

            if (buffer1.recordType() != buffer2.recordType()) {
              listener.onMessage(
                  "\n- ERR: RID="
                      + collectionId1
                      + ":"
                      + position
                      + " recordType is different: "
                      + (char) buffer1.recordType()
                      + " <-> "
                      + (char) buffer2.recordType());
              ++differences;
            }

            //noinspection StatementWithEmptyBody
            if (buffer1.buffer() == null && buffer2.buffer() == null) {
              // Both null so both equals
            } else {
              if (buffer1.buffer() == null) {
                listener.onMessage(
                    "\n- ERR: RID="
                        + collectionId1
                        + ":"
                        + position
                        + " content is different: null <-> "
                        + buffer2.buffer().length);
                ++differences;

              } else {
                if (buffer2.buffer() == null) {
                  listener.onMessage(
                      "\n- ERR: RID="
                          + collectionId1
                          + ":"
                          + position
                          + " content is different: "
                          + buffer1.buffer().length
                          + " <-> null");
                  ++differences;

                } else {
                  if (EntityHelper.isEntity(buffer1.recordType())) {
                    // ENTITY: TRY TO INSTANTIATE AND COMPARE

                    final var rec1 = (RecordAbstract) entity1;
                    rec1.unsetDirty();
                    final var rec3 = (RecordAbstract) entity1;
                    rec3.fromStream(buffer1.buffer());

                    final var rec = (RecordAbstract) entity2;
                    rec.unsetDirty();
                    final var rec2 = (RecordAbstract) entity2;
                    rec2.fromStream(buffer2.buffer());

                    if (rid1.toString().equals(configuration1.getSchemaRecordId())
                        && rid1.toString().equals(configuration2.getSchemaRecordId())) {
                      convertSchemaDoc(entity1);
                      convertSchemaDoc(entity2);
                    }

                    if (!EntityHelper.hasSameContentOf(
                        entity1, sessionOne, entity2, sessionTwo, ridMapper)) {
                      listener.onMessage(
                          "\n- ERR: RID="
                              + collectionId1
                              + ":"
                              + position
                              + " entity content is different");
                      listener.onMessage("\n--- REC1: " + new String(buffer1.buffer()));
                      listener.onMessage("\n--- REC2: " + new String(buffer2.buffer()));
                      listener.onMessage("\n");
                      ++differences;
                    }
                  } else {
                    if (buffer1.buffer().length != buffer2.buffer().length) {
                      // CHECK IF THE TRIMMED SIZE IS THE SAME
                      @SuppressWarnings("ObjectAllocationInLoop") final var rec1 = new String(
                          buffer1.buffer()).trim();
                      @SuppressWarnings("ObjectAllocationInLoop") final var rec2 = new String(
                          buffer2.buffer()).trim();

                      if (rec1.length() != rec2.length()) {
                        listener.onMessage(
                            "\n- ERR: RID="
                                + collectionId1
                                + ":"
                                + position
                                + " content length is different: "
                                + buffer1.buffer().length
                                + " <-> "
                                + buffer2.buffer().length);

                        if (EntityHelper.isEntity(buffer2.recordType())) {
                          listener.onMessage("\n--- REC2: " + rec2);
                        }

                        listener.onMessage("\n");

                        ++differences;
                      }
                    } else {
                      // CHECK BYTE PER BYTE
                      for (var b = 0; b < buffer1.buffer().length; ++b) {
                        if (buffer1.buffer()[b] != buffer2.buffer()[b]) {
                          listener.onMessage(
                              "\n- ERR: RID="
                                  + collectionId1
                                  + ":"
                                  + position
                                  + " content is different at byte #"
                                  + b
                                  + ": "
                                  + buffer1.buffer()[b]
                                  + " <-> "
                                  + buffer2.buffer()[b]);
                          listener.onMessage("\n--- REC1: " + new String(buffer1.buffer()));
                          listener.onMessage("\n--- REC2: " + new String(buffer2.buffer()));
                          listener.onMessage("\n");
                          ++differences;
                          break;
                        }
                      }
                    }
                  }
                }
              }
            }
          } catch (RuntimeException e) {
            LogManager.instance()
                .error(this, "Error during data comparison of records with rid " + rid1, e);
            throw e;
          }
        }
        final var curPosition = physicalPositions;
        physicalPositions = sessionOne.getStorage()
            .higherPhysicalPositions(sessionOne, collectionId1,
                curPosition[curPosition.length - 1], Integer.MAX_VALUE);
        if (recordsCounter % 10000 == 0) {
          listener.onMessage(
              "\n"
                  + recordsCounter
                  + " records were processed for collection "
                  + collectionName
                  + " ...");
        }
      }

      listener.onMessage(
          "\nCollection comparison was finished, "
              + recordsCounter
              + " records were processed for collection "
              + collectionName
              + " ...");
    }
  }