/* * Licensed under the Apache License, Version 2.0 (the "License"); * * You may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * limitations under the License. * * Contributions from 2013-2017 where performed either by US government * employees, or under US Veterans Health Administration contracts. * * US Veterans Health Administration contributions by government employees * are work of the U.S. Government and are not subject to copyright * protection in the United States. Portions contributed by government * employees are USGovWork (17USC ยง105). Not subject to copyright. * * Contribution by contractors to the US Veterans Health Administration * during this period are contractually contributed under the * Apache License, Version 2.0. * * See: https://www.usa.gov/government-works * * Contributions prior to 2013: * * Copyright (C) International Health Terminology Standards Development Organisation. * Licensed under the Apache License, Version 2.0. * */ package sh.isaac.provider.taxonomy; //~--- JDK imports ------------------------------------------------------------ import java.util.concurrent.ConcurrentSkipListSet; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.StampedLock; //~--- non-JDK imports -------------------------------------------------------- import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import sh.isaac.api.Get; import sh.isaac.api.TaxonomyService; import sh.isaac.api.commit.CommitRecord; import sh.isaac.api.component.sememe.SememeChronology; import sh.isaac.api.component.sememe.version.LogicGraphSememe; import sh.isaac.api.task.TimedTask; //~--- classes ---------------------------------------------------------------- /** * The Class UpdateTaxonomyAfterCommitTask. * * @author kec */ public class UpdateTaxonomyAfterCommitTask extends TimedTask<Void> { /** The Constant log. */ private static final Logger log = LogManager.getLogger(); //~--- fields -------------------------------------------------------------- /** The work done. */ int workDone = 0; /** The total work. */ int totalWork = 0; /** The taxonomy service. */ TaxonomyService taxonomyService; /** The commit record. */ CommitRecord commitRecord; /** The sememe sequences for unhandled changes. */ ConcurrentSkipListSet<Integer> sememeSequencesForUnhandledChanges; /** The lock. */ StampedLock lock; //~--- constructors -------------------------------------------------------- /** * Instantiates a new update taxonomy after commit task. * * @param taxonomyService the taxonomy service * @param commitRecord the commit record * @param sememeSequencesForUnhandledChanges the sememe sequences for unhandled changes * @param lock the lock */ private UpdateTaxonomyAfterCommitTask(TaxonomyService taxonomyService, CommitRecord commitRecord, ConcurrentSkipListSet<Integer> sememeSequencesForUnhandledChanges, StampedLock lock) { this.commitRecord = commitRecord; this.sememeSequencesForUnhandledChanges = sememeSequencesForUnhandledChanges; this.lock = lock; this.taxonomyService = taxonomyService; this.totalWork = sememeSequencesForUnhandledChanges.size(); this.updateTitle("Update taxonomy after commit"); this.updateProgress(this.workDone, this.totalWork); } //~--- methods ------------------------------------------------------------- /** * Call. * * @return the void * @throws Exception the exception */ @Override protected Void call() throws Exception { final long stamp = this.lock.writeLock(); try { final AtomicBoolean atLeastOneFailed = new AtomicBoolean(false); this.sememeSequencesForUnhandledChanges.stream().forEach((sememeSequence) -> { try { this.workDone++; this.updateProgress(this.workDone, this.totalWork); if (this.commitRecord.getSememesInCommit() .contains(sememeSequence)) { this.updateMessage("Updating taxonomy for: " + sememeSequence); this.taxonomyService.updateTaxonomy( (SememeChronology<LogicGraphSememe<?>>) Get.sememeService() .getSememe(sememeSequence)); this.sememeSequencesForUnhandledChanges.remove(sememeSequence); } } catch (final Exception e) { log.error("Error handling update taxonomy after commit on sememe " + sememeSequence, e); atLeastOneFailed.set(true); } }); if (atLeastOneFailed.get()) { throw new RuntimeException("There were errors during taxonomy update after commit"); } this.updateMessage("complete"); return null; } finally { this.lock.unlockWrite(stamp); Get.activeTasks() .remove(this); } } //~--- get methods --------------------------------------------------------- /** * Get an executing task that will update the taxonomy. * @param taxonomyService the service to update * @param commitRecord the commitRecord to process * @param unhandledChanges the changes to look for * @param lock write lock for the update * @return a task, submitted to an executor, and added to the active task set. * */ public static UpdateTaxonomyAfterCommitTask get(TaxonomyService taxonomyService, CommitRecord commitRecord, ConcurrentSkipListSet<Integer> unhandledChanges, StampedLock lock) { final UpdateTaxonomyAfterCommitTask task = new UpdateTaxonomyAfterCommitTask(taxonomyService, commitRecord, unhandledChanges, lock); Get.activeTasks() .add(task); Get.workExecutors() .getExecutor() .execute(task); return task; } }