private String incrementalBackup()

in core/src/main/java/com/jetbrains/youtrackdb/internal/core/storage/disk/DiskStorage.java [995:1142]


  private String incrementalBackup(
      final java.io.File backupDirectory, final CallableFunction<Void, Void> started) {
    var fileName = "";

    if (!backupDirectory.exists()) {
      if (!backupDirectory.mkdirs()) {
        throw new StorageException(name,
            "Backup directory "
                + backupDirectory.getAbsolutePath()
                + " does not exist and can not be created");
      }
    }
    checkNoBackupInStorageDir(backupDirectory);

    final var fileLockPath = backupDirectory.toPath().resolve(INCREMENTAL_BACKUP_LOCK);
    try (final var lockChannel =
        FileChannel.open(fileLockPath, StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {
      try (@SuppressWarnings("unused") final var fileLock = lockChannel.lock()) {
        RandomAccessFile rndIBUFile = null;
        try {
          final var files = fetchIBUFiles(backupDirectory);

          final LogSequenceNumber lastLsn;
          long nextIndex;
          final UUID backupUUID;

          if (files.length == 0) {
            lastLsn = null;
            nextIndex = 0;
          } else {
            lastLsn = extractIBULsn(backupDirectory, files[files.length - 1]);
            nextIndex = extractIndexFromIBUFile(backupDirectory, files[files.length - 1]) + 1;
            backupUUID =
                extractDbInstanceUUID(backupDirectory, files[0], configuration.getCharset());
            checkDatabaseInstanceId(backupUUID);
          }

          final var dateFormat = new SimpleDateFormat(INCREMENTAL_BACKUP_DATEFORMAT);
          if (lastLsn != null) {
            fileName =
                getName()
                    + "_"
                    + dateFormat.format(new Date())
                    + "_"
                    + nextIndex
                    + IBU_EXTENSION_V3;
          } else {
            fileName =
                getName()
                    + "_"
                    + dateFormat.format(new Date())
                    + "_"
                    + nextIndex
                    + "_full"
                    + IBU_EXTENSION_V3;
          }

          final var ibuFile = new java.io.File(backupDirectory, fileName);

          if (started != null) {
            started.call(null);
          }
          rndIBUFile = new RandomAccessFile(ibuFile, "rw");
          try {
            final var ibuChannel = rndIBUFile.getChannel();

            final var versionBuffer = ByteBuffer.allocate(IntegerSerializer.INT_SIZE);
            versionBuffer.putInt(INCREMENTAL_BACKUP_VERSION);
            versionBuffer.rewind();

            IOUtils.writeByteBuffer(versionBuffer, ibuChannel, 0);

            ibuChannel.position(
                2 * IntegerSerializer.INT_SIZE
                    + 2 * LongSerializer.LONG_SIZE
                    + ByteSerializer.BYTE_SIZE);

            LogSequenceNumber maxLsn;
            try (var stream = Channels.newOutputStream(ibuChannel)) {
              maxLsn = incrementalBackup(stream, lastLsn, true);
              final var dataBuffer =
                  ByteBuffer.allocate(
                      IntegerSerializer.INT_SIZE
                          + 2 * LongSerializer.LONG_SIZE
                          + ByteSerializer.BYTE_SIZE);

              dataBuffer.putLong(nextIndex);
              dataBuffer.putLong(maxLsn.getSegment());
              dataBuffer.putInt(maxLsn.getPosition());

              if (lastLsn == null) {
                dataBuffer.put((byte) 1);
              } else {
                dataBuffer.put((byte) 0);
              }

              dataBuffer.rewind();

              ibuChannel.write(dataBuffer);
              IOUtils.writeByteBuffer(dataBuffer, ibuChannel, IntegerSerializer.INT_SIZE);
            }
          } catch (RuntimeException e) {
            rndIBUFile.close();

            if (!ibuFile.delete()) {
              LogManager.instance()
                  .error(
                      this, ibuFile.getAbsolutePath() + " is closed but can not be deleted", null);
            }

            throw e;
          }
        } catch (IOException e) {
          throw BaseException.wrapException(
              new StorageException(name, "Error during incremental backup"), e, name);
        } finally {
          try {
            if (rndIBUFile != null) {
              rndIBUFile.close();
            }
          } catch (IOException e) {
            LogManager.instance().error(this, "Can not close %s file", e, fileName);
          }
        }
      }
    } catch (final OverlappingFileLockException e) {
      LogManager.instance()
          .error(
              this,
              "Another incremental backup process is in progress, please wait till it will be"
                  + " finished",
              null);
    } catch (final IOException e) {
      throw BaseException.wrapException(
          new StorageException(name, "Error during incremental backup"),
          e, name);
    }

    try {
      Files.deleteIfExists(fileLockPath);
    } catch (IOException e) {
      throw BaseException.wrapException(
          new StorageException(name, "Error during incremental backup"),
          e, name);
    }

    return fileName;
  }