All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.taxonic.carml.engine.reactivedev.join.MapDbChildSideJoinFileStore Maven / Gradle / Ivy

package com.taxonic.carml.engine.reactivedev.join;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.nio.file.Files;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.atomic.AtomicBoolean;
import org.mapdb.DB;
import org.mapdb.DBMaker;
import org.mapdb.Serializer;
import reactor.core.publisher.Flux;

public class MapDbChildSideJoinFileStore
    implements ChildSideJoinStore {

  private final String name;

  private final File dbFile;

  private final int commitBatchSize;

  private final AtomicBoolean dbFileUsed;

  private final BlockingQueue> tmpStorage;

  static  MapDbChildSideJoinFileStore of(String name,
      File dbFile, int commitBatchSize) {
    return new MapDbChildSideJoinFileStore<>(name, dbFile, commitBatchSize);
  }

  private MapDbChildSideJoinFileStore(String name, File dbFile, int commitBatchSize) {
    this.name = name;
    this.dbFile = dbFile;
    this.commitBatchSize = commitBatchSize;
    this.dbFileUsed = new AtomicBoolean();
    this.tmpStorage = new LinkedBlockingDeque<>();
  }

  @Override
  public void addAll(Set> childSideJoins) {
    tmpStorage.addAll(childSideJoins);
    if (tmpStorage.size() >= commitBatchSize) {
      commit();
    }
  }

  @Override
  public Flux> clearingFlux() {
    return Flux.using(this::getTransaction, this::createFlux, this::cleanup);
  }

  @SuppressWarnings("unchecked")
  private Set> openStore(DB transaction) {
    return (Set>) transaction.hashSet(name, Serializer.JAVA)
        .createOrOpen();
  }

  private void commit() {
    DB transaction = getTransaction();
    commitRunningTransaction(transaction);
  }

  private DB getTransaction() {
    return DBMaker.fileDB(dbFile)
        .closeOnJvmShutdown()
        .make();
  }

  private void commitRunningTransaction(DB transaction) {
    Set> store = openStore(transaction);
    tmpStorage.drainTo(store);
    transaction.commit();
    transaction.close();
    dbFileUsed.compareAndSet(false, true);
  }

  private Flux> createFlux(DB transaction) {
    if (dbFileUsed.get()) {
      return Flux.merge(Flux.fromIterable(tmpStorage), Flux.fromIterable(openStore(transaction)));
    } else {
      return Flux.fromIterable(tmpStorage);
    }
  }

  private void cleanup(DB transaction) {
    if (dbFileUsed.get()) {
      transaction.close();
      try {
        Files.delete(dbFile.toPath());
      } catch (IOException ioException) {
        throw new MapDbStoreException(String.format("Error deleting temp file %s", dbFile), ioException);
      }
    }

    tmpStorage.clear();
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy