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

org.molgenis.data.index.job.IndexStatus Maven / Gradle / Ivy

There is a newer version: 8.4.5
Show newest version
package org.molgenis.data.index.job;

import static com.google.common.collect.Streams.stream;
import static java.util.stream.Collectors.toSet;

import com.google.common.util.concurrent.AtomicLongMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.molgenis.data.meta.model.Attribute;
import org.molgenis.data.meta.model.EntityType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** Keeps track of outstanding index actions. */
public class IndexStatus {
  private final Lock lock = new ReentrantLock();
  private final Condition allEntitiesStable = lock.newCondition();
  private final Condition singleEntityStable = lock.newCondition();

  /** Counts how many actions are pending for each entity. */
  private AtomicLongMap actionCountsPerEntity = AtomicLongMap.create();

  private static final Logger LOG = LoggerFactory.getLogger(IndexStatus.class);

  void addActionCounts(Map actionsRegistered) {
    LOG.debug("addActionCounts {}", actionsRegistered);
    lock.lock();
    try {
      for (Map.Entry addedForEntity : actionsRegistered.entrySet()) {
        final String entityTypeId = addedForEntity.getKey();
        final Long numberOfActions = addedForEntity.getValue();
        actionCountsPerEntity.addAndGet(entityTypeId, numberOfActions);
      }
    } finally {
      lock.unlock();
    }
  }

  void removeActionCounts(Map actionsPerformed) {
    LOG.debug("removeActionCount {}", actionsPerformed);
    lock.lock();
    try {
      for (Map.Entry actionsPerEntity : actionsPerformed.entrySet()) {
        final String entityTypeId = actionsPerEntity.getKey();
        Long numberOfActions = actionsPerEntity.getValue();
        if (actionCountsPerEntity.addAndGet(entityTypeId, -numberOfActions) == 0) {
          actionCountsPerEntity.removeAllZeros();
          LOG.debug("Entity {} is stable.", entityTypeId);
          singleEntityStable.signalAll();
        }
      }
      if (isAllIndicesStable()) {
        LOG.debug("All entities stable.");
        allEntitiesStable.signalAll();
      }
    } finally {
      lock.unlock();
    }
  }

  void waitForAllEntitiesToBeStable() throws InterruptedException {
    lock.lock();
    try {
      while (!isAllIndicesStable()) {
        allEntitiesStable.await();
      }
    } finally {
      lock.unlock();
    }
  }

  private boolean isIndexStableIncludingReferences(EntityType emd) {
    if (isAllIndicesStable()) {
      return true;
    }
    Set referencedEntityIds =
        stream(emd.getAtomicAttributes())
            .filter(Attribute::hasRefEntity)
            .map(attribute -> attribute.getRefEntity().getId())
            .collect(toSet());
    referencedEntityIds.add(emd.getId());
    return referencedEntityIds.stream().noneMatch(actionCountsPerEntity::containsKey);
  }

  void waitForIndexToBeStableIncludingReferences(EntityType emd) throws InterruptedException {
    lock.lock();
    try {
      while (!isIndexStableIncludingReferences(emd)) {
        singleEntityStable.await();
      }
    } finally {
      lock.unlock();
    }
  }

  private boolean isAllIndicesStable() {
    return actionCountsPerEntity.isEmpty();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy