Search in sources :

Example 1 with RUNNABLE

use of com.evolveum.midpoint.xml.ns._public.common.common_3.TaskExecutionStateType.RUNNABLE in project midpoint by Evolveum.

the class OrgClosureConcurrencyTest method _test300AddRemoveNodesMT.

protected void _test300AddRemoveNodesMT(final boolean random) throws Exception {
    OperationResult opResult = new OperationResult("===[ test300AddRemoveNodesMT ]===");
    info("test300AddRemoveNodes starting with random = " + random);
    final Set<ObjectType> nodesToRemove = Collections.synchronizedSet(new HashSet<>());
    final Set<ObjectType> nodesToAdd = Collections.synchronizedSet(new HashSet<>());
    final List<Throwable> exceptions = Collections.synchronizedList(new ArrayList<>());
    for (int level = 0; level < getConfiguration().getNodeRoundsForLevel().length; level++) {
        int rounds = getConfiguration().getNodeRoundsForLevel()[level];
        List<String> levelOids = orgsByLevels.get(level);
        generateNodesAtOneLevel(nodesToRemove, nodesToAdd, OrgType.class, rounds, levelOids, opResult);
    }
    int numberOfRunners = THREADS;
    final List<Thread> runners = Collections.synchronizedList(new ArrayList<>());
    for (int i = 0; i < numberOfRunners; i++) {
        Runnable runnable = new Runnable() {

            @Override
            public void run() {
                try {
                    while (true) {
                        ObjectType objectType = getNext(nodesToRemove, random);
                        if (objectType == null) {
                            break;
                        }
                        logger.info("Removing {}", objectType);
                        int remaining;
                        try {
                            removeObject(objectType);
                            synchronized (OrgClosureConcurrencyTest.this) {
                                nodesToRemove.remove(objectType);
                                remaining = nodesToRemove.size();
                            }
                            info(Thread.currentThread().getName() + " removed " + objectType + "; remaining: " + remaining);
                        } catch (ObjectNotFoundException e) {
                            // this is OK
                            info(Thread.currentThread().getName() + ": " + objectType + " already deleted");
                            // give other threads a chance
                            Thread.sleep(300);
                        }
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                    exceptions.add(e);
                } finally {
                    runners.remove(Thread.currentThread());
                }
            }
        };
        Thread t = new Thread(runnable);
        runners.add(t);
        t.start();
    }
    waitForRunnersCompletion(runners);
    if (!nodesToRemove.isEmpty()) {
        throw new AssertionError("Nodes to remove is not empty, see the console or log: " + nodesToRemove);
    }
    if (!exceptions.isEmpty()) {
        throw new AssertionError("Found exceptions: " + exceptions);
    }
    rebuildGraph();
    checkClosure(orgGraph.vertexSet());
    info("Consistency after removing OK");
    numberOfRunners = THREADS;
    for (int i = 0; i < numberOfRunners; i++) {
        Runnable runnable = new Runnable() {

            @Override
            public void run() {
                try {
                    while (true) {
                        ObjectType objectType = getNext(nodesToAdd, random);
                        if (objectType == null) {
                            break;
                        }
                        logger.info("Adding {}", objectType);
                        try {
                            addObject(objectType.clone());
                            // rebuildGraph();
                            // checkClosure(orgGraph.vertexSet());
                            int remaining;
                            synchronized (OrgClosureConcurrencyTest.this) {
                                nodesToAdd.remove(objectType);
                                remaining = nodesToAdd.size();
                            }
                            info(Thread.currentThread().getName() + " re-added " + objectType + "; remaining: " + remaining);
                        } catch (ObjectAlreadyExistsException e) {
                            // this is OK
                            info(Thread.currentThread().getName() + ": " + objectType + " already exists");
                            // give other threads a chance
                            Thread.sleep(300);
                        }
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                    exceptions.add(e);
                } finally {
                    runners.remove(Thread.currentThread());
                }
            }
        };
        Thread t = new Thread(runnable);
        runners.add(t);
        t.start();
    }
    waitForRunnersCompletion(runners);
    if (!nodesToAdd.isEmpty()) {
        throw new AssertionError("Nodes to add is not empty, see the console or log: " + nodesToAdd);
    }
    if (!exceptions.isEmpty()) {
        throw new AssertionError("Found exceptions: " + exceptions);
    }
    rebuildGraph();
    checkClosure(orgGraph.vertexSet());
    info("Consistency after re-adding OK");
}
Also used : OperationResult(com.evolveum.midpoint.schema.result.OperationResult) ObjectType(com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType) ObjectNotFoundException(com.evolveum.midpoint.util.exception.ObjectNotFoundException) ObjectAlreadyExistsException(com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException)

Example 2 with RUNNABLE

use of com.evolveum.midpoint.xml.ns._public.common.common_3.TaskExecutionStateType.RUNNABLE in project midpoint by Evolveum.

the class OrgClosureConcurrencyTest method _test200AddRemoveLinksMT.

/**
 * We randomly select a set of links to be removed.
 * Then we remove them, using a given set of threads.
 * After all threads are done, we will check the closure table consistency.
 * <p>
 * And after that, we will do the reverse, re-adding all the links previously removed.
 * In the end, we again check the consistency.
 */
protected void _test200AddRemoveLinksMT(final boolean random) throws Exception {
    OperationResult opResult = new OperationResult("===[ test200AddRemoveLinksMT ]===");
    info("test200AddRemoveLinks starting with random = " + random);
    final Set<Edge> edgesToRemove = Collections.synchronizedSet(new HashSet<>());
    final Set<Edge> edgesToAdd = Collections.synchronizedSet(new HashSet<>());
    final List<Throwable> exceptions = Collections.synchronizedList(new ArrayList<>());
    // parentRef link removal + addition
    for (int level = 0; level < getConfiguration().getLinkRoundsForLevel().length; level++) {
        int rounds = getConfiguration().getLinkRoundsForLevel()[level];
        List<String> levelOids = orgsByLevels.get(level);
        int retries = 0;
        for (int round = 0; round < rounds; round++) {
            int index = (int) Math.floor(Math.random() * levelOids.size());
            String oid = levelOids.get(index);
            OrgType org = repositoryService.getObject(OrgType.class, oid, null, opResult).asObjectable();
            // check if it has no parents (shouldn't occur here!)
            if (org.getParentOrgRef().isEmpty()) {
                throw new IllegalStateException("No parents in " + org);
            }
            int i = (int) Math.floor(Math.random() * org.getParentOrgRef().size());
            ObjectReferenceType parentOrgRef = org.getParentOrgRef().get(i);
            Edge edge = new Edge(oid, parentOrgRef.getOid());
            if (edgesToRemove.contains(edge)) {
                round--;
                if (++retries == 1000) {
                    // primitive attempt to break potential cycles when there is not enough edges to process
                    throw new IllegalStateException("Too many retries");
                } else {
                    continue;
                }
            }
            edgesToRemove.add(edge);
            edgesToAdd.add(edge);
        }
    }
    int numberOfRunners = THREADS;
    info("Edges to remove/add (" + edgesToRemove.size() + ": " + edgesToRemove);
    info("Number of runners: " + numberOfRunners);
    final List<Thread> runners = Collections.synchronizedList(new ArrayList<>());
    for (int i = 0; i < numberOfRunners; i++) {
        Runnable runnable = new Runnable() {

            @Override
            public void run() {
                try {
                    while (true) {
                        Edge edge = getNext(edgesToRemove, random);
                        if (edge == null) {
                            break;
                        }
                        logger.info("Removing {}", edge);
                        removeEdge(edge);
                        int remaining;
                        synchronized (OrgClosureConcurrencyTest.this) {
                            edgesToRemove.remove(edge);
                            remaining = edgesToRemove.size();
                        }
                        info(Thread.currentThread().getName() + " removed " + edge + "; remaining: " + remaining);
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                    exceptions.add(e);
                } finally {
                    runners.remove(Thread.currentThread());
                }
            }
        };
        Thread t = new Thread(runnable);
        runners.add(t);
        t.start();
    }
    waitForRunnersCompletion(runners);
    if (!edgesToRemove.isEmpty()) {
        throw new AssertionError("Edges to remove is not empty, see the console or log: " + edgesToRemove);
    }
    if (!exceptions.isEmpty()) {
        throw new AssertionError("Found exceptions: " + exceptions);
    }
    checkClosure(orgGraph.vertexSet());
    info("Consistency after removal OK");
    for (int i = 0; i < numberOfRunners; i++) {
        Runnable runnable = new Runnable() {

            @Override
            public void run() {
                try {
                    while (true) {
                        Edge edge = getNext(edgesToAdd, random);
                        if (edge == null) {
                            break;
                        }
                        logger.info("Adding {}", edge);
                        addEdge(edge);
                        int remaining;
                        synchronized (OrgClosureConcurrencyTest.this) {
                            edgesToAdd.remove(edge);
                            remaining = edgesToAdd.size();
                        }
                        info(Thread.currentThread().getName() + " re-added " + edge + "; remaining: " + remaining);
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                    exceptions.add(e);
                } finally {
                    runners.remove(Thread.currentThread());
                }
            }
        };
        Thread t = new Thread(runnable);
        runners.add(t);
        t.start();
    }
    waitForRunnersCompletion(runners);
    if (!edgesToAdd.isEmpty()) {
        throw new AssertionError("Edges to add is not empty, see the console or log: " + edgesToAdd);
    }
    if (!exceptions.isEmpty()) {
        throw new AssertionError("Found exceptions: " + exceptions);
    }
    checkClosure(orgGraph.vertexSet());
    info("Consistency after re-adding OK");
}
Also used : OperationResult(com.evolveum.midpoint.schema.result.OperationResult) ObjectReferenceType(com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType) OrgType(com.evolveum.midpoint.xml.ns._public.common.common_3.OrgType) Edge(com.evolveum.midpoint.repo.sql.helpers.OrgClosureManager.Edge)

Example 3 with RUNNABLE

use of com.evolveum.midpoint.xml.ns._public.common.common_3.TaskExecutionStateType.RUNNABLE in project midpoint by Evolveum.

the class ExtDictionaryTest method test100ParallelAdd.

@Test
public void test100ParallelAdd() throws Exception {
    for (int round = 0; round < ROUNDS; round++) {
        List<TestingThread> threads = new ArrayList<>();
        for (int i = 0; i < THREADS; i++) {
            final int round1 = round;
            final int thread1 = i;
            Runnable runnable = () -> {
                try {
                    UserType user = new UserType(prismContext).name("u-" + round1 + "-" + thread1);
                    QName propertyName = new QName(NS_TEST, "round" + round1);
                    MutablePrismPropertyDefinition<String> propertyDefinition = prismContext.definitionFactory().createPropertyDefinition(propertyName, DOMUtil.XSD_STRING);
                    PrismProperty<String> property = propertyDefinition.instantiate();
                    property.setRealValue("value");
                    user.asPrismObject().addExtensionItem(property);
                    repositoryService.addObject(user.asPrismObject(), null, new OperationResult("addObject"));
                } catch (RuntimeException e) {
                    throw e;
                } catch (Exception e) {
                    throw new SystemException(e);
                }
            };
            TestingThread thread = new TestingThread(runnable);
            threads.add(thread);
            thread.start();
        }
        for (int i = 0; i < THREADS; i++) {
            TestingThread thread = threads.get(i);
            thread.join(60000L);
            if (thread.throwable != null) {
                fail("Exception in " + thread + ": " + thread.throwable);
            }
        }
    }
    Session session = open();
    // noinspection unchecked
    List<RExtItem> extItems = session.createQuery("from RExtItem").list();
    System.out.println("ext items: " + extItems.size());
    for (RExtItem extItem : extItems) {
        System.out.println(extItem);
        logger.info("{}", extItem);
    }
    session.close();
}
Also used : QName(javax.xml.namespace.QName) ArrayList(java.util.ArrayList) OperationResult(com.evolveum.midpoint.schema.result.OperationResult) SystemException(com.evolveum.midpoint.util.exception.SystemException) PrismProperty(com.evolveum.midpoint.prism.PrismProperty) SystemException(com.evolveum.midpoint.util.exception.SystemException) RExtItem(com.evolveum.midpoint.repo.sql.data.common.any.RExtItem) MutablePrismPropertyDefinition(com.evolveum.midpoint.prism.MutablePrismPropertyDefinition) UserType(com.evolveum.midpoint.xml.ns._public.common.common_3.UserType) Session(org.hibernate.Session) Test(org.testng.annotations.Test)

Example 4 with RUNNABLE

use of com.evolveum.midpoint.xml.ns._public.common.common_3.TaskExecutionStateType.RUNNABLE in project midpoint by Evolveum.

the class TaskSynchronizer method synchronizeTask.

/**
 * Task should be refreshed when entering this method.
 *
 * @return true if task info in Quartz was updated
 */
public boolean synchronizeTask(TaskQuartzImpl task, OperationResult parentResult) {
    if (!task.isPersistent()) {
        // transient tasks are not scheduled via Quartz!
        return false;
    }
    boolean changed = false;
    StringBuilder message = new StringBuilder();
    OperationResult result = parentResult.createSubresult(OP_SYNCHRONIZE_TASK);
    result.addArbitraryObjectAsParam("task", task);
    try {
        taskMigrator.migrateIfNeeded(task, result);
        LOGGER.trace("Synchronizing task {}; isRecreateQuartzTrigger = {}", task, task.isRecreateQuartzTrigger());
        Scheduler scheduler = localScheduler.getQuartzScheduler();
        String oid = task.getOid();
        JobKey jobKey = QuartzUtil.createJobKeyForTask(task);
        TriggerKey standardTriggerKey = QuartzUtil.createTriggerKeyForTask(task);
        TaskSchedulingStateType schedulingState = task.getSchedulingState();
        boolean waitingOrClosedOrSuspended = schedulingState == TaskSchedulingStateType.WAITING || schedulingState == TaskSchedulingStateType.CLOSED || schedulingState == TaskSchedulingStateType.SUSPENDED;
        if (!scheduler.checkExists(jobKey) && !waitingOrClosedOrSuspended) {
            String m1 = "Quartz job does not exist for a task, adding it. Task = " + task;
            message.append("[").append(m1).append("] ");
            LOGGER.trace(" - {}", m1);
            scheduler.addJob(QuartzUtil.createJobDetailForTask(task), false);
            changed = true;
        }
        // CLOSED tasks should have no triggers; SUSPENDED and WAITING tasks should have no extra triggers
        List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
        boolean standardTriggerExists = triggers.stream().anyMatch(t -> t.getKey().equals(standardTriggerKey));
        if (waitingOrClosedOrSuspended) {
            for (Trigger trigger : triggers) {
                if (schedulingState == TaskSchedulingStateType.CLOSED || !trigger.getKey().equals(standardTriggerKey)) {
                    String m1 = "Removing Quartz trigger " + trigger.getKey() + " for WAITING/CLOSED/SUSPENDED task " + task;
                    message.append("[").append(m1).append("] ");
                    LOGGER.trace(" - {}", m1);
                    scheduler.unscheduleJob(trigger.getKey());
                    changed = true;
                } else {
                // For SUSPENDED/WAITING tasks, we keep the standard trigger untouched. We want to preserve original
                // scheduled time. (This might or might not be what the user wants ... but it has been so for so
                // many years, so let's not change it now.)
                // 
                // It's harmless to keep the standard trigger, because:
                // 1) If a trigger is mistakenly alive, JobExecutor will take care of it.
                // 2) If a trigger has wrong parameters, this will be corrected on task resume/unpause.
                }
            }
        } else if (schedulingState == TaskSchedulingStateType.READY) {
            Trigger triggerToBe;
            try {
                triggerToBe = QuartzUtil.createTriggerForTask(task);
            } catch (ParseException e) {
                String message2 = "Cannot create a trigger for a task " + this + " because of a cron expression parsing exception";
                LoggingUtils.logUnexpectedException(LOGGER, message2, e);
                result.recordFatalError(message2, e);
                // TODO: implement error handling correctly
                throw new SystemException("Cannot a trigger for a task because of a cron expression parsing exception", e);
            }
            if (triggerToBe == null) {
                if (standardTriggerExists) {
                    // TODO what about non-standard triggers?
                    // These may be legal here (e.g. for a manually-run recurring task waiting to get a chance to run)
                    String m1 = "Removing standard Quartz trigger for RUNNABLE task that should not have it; task = " + task;
                    message.append("[").append(m1).append("] ");
                    LOGGER.trace(" - " + m1);
                    scheduler.unscheduleJob(TriggerKey.triggerKey(oid));
                    changed = true;
                }
            } else {
                // if the trigger should exist and it does not...
                if (!standardTriggerExists) {
                    String m1 = "Creating standard trigger for a RUNNABLE task " + task;
                    LOGGER.trace(" - " + m1);
                    message.append("[").append(m1).append("] ");
                    scheduler.scheduleJob(triggerToBe);
                    changed = true;
                } else {
                    // we have to compare trigger parameters with the task's ones
                    Trigger triggerAsIs = scheduler.getTrigger(standardTriggerKey);
                    if (task.isRecreateQuartzTrigger() || QuartzUtil.triggersDiffer(triggerAsIs, triggerToBe)) {
                        String m1 = "Existing trigger has incompatible parameters or was explicitly requested to be recreated; recreating it. Task = " + task;
                        LOGGER.trace(" - " + m1);
                        message.append("[").append(m1).append("] ");
                        scheduler.rescheduleJob(standardTriggerKey, triggerToBe);
                        changed = true;
                    } else {
                        String m1 = "Existing trigger is OK, leaving it as is; task = " + task;
                        LOGGER.trace(" - " + m1);
                        message.append("[").append(m1).append("] ");
                        Trigger.TriggerState state = scheduler.getTriggerState(standardTriggerKey);
                        if (state == Trigger.TriggerState.PAUSED) {
                            String m2 = "However, the trigger is paused, resuming it; task = " + task;
                            LOGGER.trace(" - " + m2);
                            message.append("[").append(m2).append("] ");
                            scheduler.resumeTrigger(standardTriggerKey);
                            changed = true;
                        }
                    }
                }
            }
        }
    } catch (Exception e) {
        String message2 = "Cannot synchronize repository/Quartz Job Store information for task " + task;
        LoggingUtils.logUnexpectedException(LOGGER, message2, e);
        result.recordFatalError(message2, e);
    } finally {
        if (result.isUnknown()) {
            result.computeStatus();
            result.recordStatus(result.getStatus(), message.toString());
        }
    }
    LOGGER.trace("synchronizeTask finishing (changed: {}) for {}", changed, task);
    return changed;
}
Also used : Scheduler(org.quartz.Scheduler) OperationResult(com.evolveum.midpoint.schema.result.OperationResult) SchemaException(com.evolveum.midpoint.util.exception.SchemaException) SchedulerException(org.quartz.SchedulerException) ParseException(java.text.ParseException) ObjectNotFoundException(com.evolveum.midpoint.util.exception.ObjectNotFoundException) SystemException(com.evolveum.midpoint.util.exception.SystemException) TriggerKey(org.quartz.TriggerKey) JobKey(org.quartz.JobKey) Trigger(org.quartz.Trigger) SystemException(com.evolveum.midpoint.util.exception.SystemException) TaskSchedulingStateType(com.evolveum.midpoint.xml.ns._public.common.common_3.TaskSchedulingStateType) ParseException(java.text.ParseException)

Example 5 with RUNNABLE

use of com.evolveum.midpoint.xml.ns._public.common.common_3.TaskExecutionStateType.RUNNABLE in project midpoint by Evolveum.

the class AbstractRepositorySearchAction method execute.

@Override
public void execute() throws Exception {
    OperationResult result = new OperationResult(getOperationName());
    OperationStatus operation = new OperationStatus(context, result);
    // "+ 2" will be used for consumer and progress reporter
    ExecutorService executor = Executors.newFixedThreadPool(options.getMultiThread() + 2);
    BlockingQueue<ObjectType> queue = new LinkedBlockingQueue<>(QUEUE_CAPACITY_PER_THREAD * options.getMultiThread());
    List<SearchProducerWorker> producers = createProducers(queue, operation);
    log.info("Starting " + getOperationShortName());
    operation.start();
    // execute as many producers as there are threads for them
    for (int i = 0; i < producers.size() && i < options.getMultiThread(); i++) {
        executor.execute(producers.get(i));
    }
    Thread.sleep(CONSUMERS_WAIT_FOR_START);
    executor.execute(new ProgressReporterWorker<>(context, options, queue, operation));
    Runnable consumer = createConsumer(queue, operation);
    executor.execute(consumer);
    // execute rest of the producers
    for (int i = options.getMultiThread(); i < producers.size(); i++) {
        executor.execute(producers.get(i));
    }
    executor.shutdown();
    boolean awaitResult = executor.awaitTermination(NinjaUtils.WAIT_FOR_EXECUTOR_FINISH, TimeUnit.DAYS);
    if (!awaitResult) {
        log.error("Executor did not finish before timeout");
    }
    handleResultOnFinish(operation, "Finished " + getOperationShortName());
}
Also used : SearchProducerWorker(com.evolveum.midpoint.ninja.action.worker.SearchProducerWorker) ObjectType(com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType) OperationStatus(com.evolveum.midpoint.ninja.util.OperationStatus) OperationResult(com.evolveum.midpoint.schema.result.OperationResult)

Aggregations

OperationResult (com.evolveum.midpoint.schema.result.OperationResult)8 ObjectNotFoundException (com.evolveum.midpoint.util.exception.ObjectNotFoundException)3 OperationStatus (com.evolveum.midpoint.ninja.util.OperationStatus)2 SystemException (com.evolveum.midpoint.util.exception.SystemException)2 AuditEventRecordType (com.evolveum.midpoint.xml.ns._public.common.audit_3.AuditEventRecordType)2 ObjectType (com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType)2 TaskSchedulingStateType (com.evolveum.midpoint.xml.ns._public.common.common_3.TaskSchedulingStateType)2 QName (javax.xml.namespace.QName)2 AuthorizationAction (com.evolveum.midpoint.authentication.api.authorization.AuthorizationAction)1 PageDescriptor (com.evolveum.midpoint.authentication.api.authorization.PageDescriptor)1 AuthUtil (com.evolveum.midpoint.authentication.api.util.AuthUtil)1 LocalizationService (com.evolveum.midpoint.common.LocalizationService)1 GuiStyleConstants (com.evolveum.midpoint.gui.api.GuiStyleConstants)1 SubscriptionType (com.evolveum.midpoint.gui.api.SubscriptionType)1 BasePanel (com.evolveum.midpoint.gui.api.component.BasePanel)1 MainObjectListPanel (com.evolveum.midpoint.gui.api.component.MainObjectListPanel)1 WrapperContext (com.evolveum.midpoint.gui.api.factory.wrapper.WrapperContext)1 LoadableModel (com.evolveum.midpoint.gui.api.model.LoadableModel)1 NonEmptyModel (com.evolveum.midpoint.gui.api.model.NonEmptyModel)1 ReadOnlyModel (com.evolveum.midpoint.gui.api.model.ReadOnlyModel)1