/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ package org.apache.felix.ipojo.extender.internal.queue; import org.apache.felix.ipojo.extender.queue.Callback; import org.apache.felix.ipojo.extender.queue.Job; import org.apache.felix.ipojo.extender.queue.JobInfo; import java.util.concurrent.Callable; /** * A callable computing job statistics. The job is given as another callable. * The statistics are global, so must be used carefully. */ public class JobInfoCallable<T> implements Callable<T>, JobInfo { /** * Notifier helper for {@link org.apache.felix.ipojo.extender.queue.QueueListener}. */ private final QueueNotifier m_queueNotifier; /** * The statistic object. */ private final Statistic m_statistic; /** * The genuine job. */ private final Job<T> m_delegate; /** * A callback notified when the job is processed. */ private final Callback<T> m_callback; /** * The job description. */ private final String m_description; /** * The date (in milli) when this object is created. */ private long enlistmentTime = System.currentTimeMillis(); /** * The date when the job processing started. */ private long startTime = -1; /** * The date when the job processing is completed. */ private long endTime = -1; /** * Creates the job info callable. * * @param queueNotifier notifier for QueueListeners * @param statistic the statistics that will be populated * @param delegate the real job * @param callback the callback notified when the job is completed * @param description the job description */ public JobInfoCallable(QueueNotifier queueNotifier, Statistic statistic, Job<T> delegate, Callback<T> callback, String description) { m_queueNotifier = queueNotifier; m_statistic = statistic; m_delegate = delegate; m_callback = callback; m_description = description; m_statistic.getWaiters().add(this); // Assume that we will be enlisted in the next few cycles m_queueNotifier.fireEnlistedJobInfo(this); } /** * Executes the job. * This method updates the statistics. * * @return the job result * @throws Exception the job execution failed */ public T call() throws Exception { m_statistic.getWaiters().remove(this); startTime = System.currentTimeMillis(); m_statistic.getCurrentsCounter().incrementAndGet(); T result = null; Exception exception = null; try { m_queueNotifier.fireStartedJobInfo(this); result = m_delegate.call(); endTime = System.currentTimeMillis(); return result; } catch (Exception e) { endTime = System.currentTimeMillis(); m_queueNotifier.fireFailedJobInfo(this, e); if (m_callback != null) { m_callback.error(this, e); } exception = e; throw e; } finally { m_statistic.getCurrentsCounter().decrementAndGet(); m_statistic.getFinishedCounter().incrementAndGet(); // Only exec success callbacks when no error occurred if (exception == null) { m_queueNotifier.fireExecutedJobInfo(this, result); if (m_callback != null) { m_callback.success(this, result); } } } } /** * @return the enlistment date. */ public long getEnlistmentTime() { return enlistmentTime; } /** * @return the job start date. */ public long getStartTime() { return startTime; } /** * @return the job completion date. */ public long getEndTime() { return endTime; } /** * Computes the time spent in the waiting queue * * @return the waited time, if the job is still waiting, gets the current waited time */ public long getWaitDuration() { long end = startTime; if (end == -1) { // Not yet started // Still waiting end = System.currentTimeMillis(); } return end - enlistmentTime; } /** * Computes the time spent to execute the job (this does not include the waiting). * If the job is not executed yet, or is still executing, {@literal -1} is returned * * @return the execution duration, or {@literal -1}. */ public long getExecutionDuration() { if ((startTime == -1) || (endTime == -1)) { return -1; } return endTime - startTime; } /** * @return the job description */ public String getDescription() { return m_description; } public String getJobType() { return m_delegate.getJobType(); } }