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

com.dell.cpsd.service.common.client.manager.AbstractServiceCallbackManager Maven / Gradle / Ivy

/**
 * Copyright © 2017 Dell Inc. or its subsidiaries. All Rights Reserved. 
 * Dell EMC Confidential/Proprietary Information
 */

package com.dell.cpsd.service.common.client.manager;

import com.dell.cpsd.common.logging.ILogger;
import com.dell.cpsd.service.common.client.callback.IServiceCallback;
import com.dell.cpsd.service.common.client.callback.ServiceCallback;
import com.dell.cpsd.service.common.client.callback.ServiceTimeout;
import com.dell.cpsd.service.common.client.exception.ServiceTimeoutException;
import com.dell.cpsd.service.common.client.log.SCCLLoggingManager;
import com.dell.cpsd.service.common.client.log.SCCLMessageCode;
import com.dell.cpsd.service.common.client.task.ITimeoutTaskManager;
import com.dell.cpsd.service.common.client.task.ServiceTask;
import com.dell.cpsd.service.common.client.task.TimeoutTask;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * This class is responsible for handling service callbacks at the client.
 * 
 * 

* Copyright © 2017 Dell Inc. or its subsidiaries. All Rights Reserved. * Dell EMC Confidential/Proprietary Information *

* * @version 1.0 * * @since 1.0 */ public abstract class AbstractServiceCallbackManager implements ITimeoutTaskManager { /* * The logger for this class. */ private static final ILogger LOGGER = SCCLLoggingManager .getLogger(AbstractServiceCallbackManager.class); /* * The infinite timeout for a request. */ private static final long INFINITE_TIMEOUT = -1l; /* * The flag to indicate that this manager is shutting down. */ private volatile boolean shutdown = false; /* * The map of correlation identifier to IServiceCallbacks */ private Map>> requests = null; /* * The ScheduledExecutorService used to check for timed out tasks. */ private ScheduledExecutorService executorService = null; /** * AbstractServiceCallbackManager constructor. * * @since 1.0 */ public AbstractServiceCallbackManager() { super(); this.requests = new HashMap>>(); this.executorService = this.makeScheduledExecutorService(1000l, 1000l, TimeUnit.MILLISECONDS); } /** * This returns true if this manager is shutting down. * * @return True if this manager is shutting down. * * @since 1.0 */ public boolean isShutDown() { return this.shutdown; } /** * This adds a service task, with its corresponding request identifier, to the managed requests. * * @param requestId * The request identifier. * @param serviceTask * The service task to add. * * @since 1.0 */ public void addServiceTask(final String requestId, final ServiceTask> serviceTask) { if (requestId == null) { return; } if (serviceTask == null) { return; } // add the callback using the requestId identifier as key synchronized (this.requests) { this.requests.put(requestId, serviceTask); } } /** * This removes the service task with the specified request identifier * * @param requestId * The request identifier. * * @return The serivce task with the specified identifier, or null. * * @since 1.0 */ public ServiceTask> removeServiceTask(final String requestId) { synchronized (this.requests) { return this.requests.remove(requestId); } } /** * This returns the service task using the specified request identifier * * @param requestId * The request identifier. * * @return The serivce task with the specified identifier, or null. * * @since 1.0 */ public ServiceTask> getServiceTask(final String requestId) { synchronized (this.requests) { return this.requests.get(requestId); } } /** * This returns the IServiceCallback for the specified request identifier, or null. * * @param requestId * The request identifier. * * @return The service callback for the identifier, or null. * * @since 1.0 */ public IServiceCallback removeServiceCallback(final String requestId) { if (requestId == null) { return null; } ServiceTask> task = null; synchronized (this.requests) { task = this.requests.remove(requestId); } if (task == null) { return null; } return task.getServiceCallback(); } /** * This cancels the request with the specified identifier. * * @param requestId * The request identifier * @return whether the request was cancelled or not */ public boolean cancel(final String requestId) { if (requestId == null) { return false; } ServiceTask> task = null; synchronized (this.requests) { task = this.requests.remove(requestId); } return (task != null); } /** * This releases any resources associated with this manager. * * @since 1.0 */ public void release() { // if the manager has already been shutdown then return if (this.shutdown) { return; } // set the shutdown flag which will cause requests to be rejected this.shutdown = true; LOGGER.info(SCCLMessageCode.EXECUTOR_SHUTDOWN_I.getMessageCode()); this.shutdown(this.executorService); // wait for the current set of requests to complete and clear down LOGGER.info(SCCLMessageCode.WAIT_ON_REQUESTS_I.getMessageCode()); this.waitForRequests(10000l); } /** * {@inheritDoc} */ @Override public void checkForTimedoutTasks() { final List>> timedOutTasks = new ArrayList>>(); String[] keyArray = null; synchronized (this.requests) { final Set keySet = this.requests.keySet(); keyArray = keySet.toArray(new String[keySet.size()]); } long currentTime = System.currentTimeMillis(); for (int i = 0; i < keyArray.length; i++) { final String requestId = keyArray[i]; ServiceTask> task = this.requests.get(requestId); if (task == null) { continue; } if (task.hasTimedout(currentTime)) { synchronized (this.requests) { task = this.requests.remove(requestId); if (task != null) { timedOutTasks.add(task); } } } } for (int i = 0; i < timedOutTasks.size(); i++) { final ServiceTask> task = timedOutTasks.get(i); final IServiceCallback callback = task.getServiceCallback(); final ServiceTimeout timeout = new ServiceTimeout(task.getRequestId(), task.getTimeout()); // TODO : Take the callback processing off the timeout thread try { callback.handleServiceTimeout(timeout); } catch (Exception exception) { // log the exception thrown by the callback Object[] lparams = {"handleServiceTimeout", exception.getMessage()}; LOGGER.error(SCCLMessageCode.ERROR_CALLBACK_FAIL_E.getMessageCode(), lparams, exception); } } } /** * This creates the ScheduledExecutorService for this manager. * * @param initialDelay * The time to delay first execution. * @param delay * The period between successive executions. * @param timeUnit * The TimeUnit for the delays. * * @return The ScheduledExecutorService for this manager. * * @since 1.0 */ protected ScheduledExecutorService makeScheduledExecutorService(long initialDelay, long delay, TimeUnit timeUnit) { TimeoutTask timeoutTask = new TimeoutTask(this); final ScheduledExecutorService newExecutorService = Executors.newSingleThreadScheduledExecutor(); newExecutorService.scheduleWithFixedDelay(timeoutTask, initialDelay, delay, TimeUnit.MILLISECONDS); return newExecutorService; } /** * This waits for any currently running requests to complete and clear down. * * @param timeout * The time in milliseconds to wait. * * @return True if all requests were completed, otherwise false. * * @since 1.0 */ protected boolean waitForRequests(long timeout) { if ((this.requests == null) || (this.requests.size() == 0)) { return true; } long timeLimit = timeout; long sleepTime = 250l; long elapsedTime = 0; // wait for the requests to complete and clear down while (this.requests.size() > 0) { try { Thread.sleep(sleepTime); } catch (InterruptedException exception) { } elapsedTime += sleepTime; if (elapsedTime >= timeLimit) { // clear the requests this.requests.clear(); return false; } } return true; } /** * This shuts down the specified ExecutorService. * * @param executorService * The ExecutorService to shutdown. * * @since 1.0 */ protected void shutdown(final ExecutorService executorService) { if (executorService == null) { return; } // stop new tasks from being submitted executorService.shutdown(); try { boolean graceful = executorService.awaitTermination(3, TimeUnit.SECONDS); // allow pending tasks to finish if (!graceful) { // cancel currently executing tasks executorService.shutdownNow(); executorService.awaitTermination(3, TimeUnit.SECONDS); } } catch (InterruptedException ie) { // (re-)cancel if current thread also interrupted executorService.shutdownNow(); // preserve interrupt status Thread.currentThread().interrupt(); } } /** * This waits the specified timeout for the service callback. * * @param serviceCallback * The service callback. * @param requestId * The request identifier. * @param timeout * The wait time period. * * @throws ServiceTimeoutException * Thrown if there is a timeout. * * @since 1.0 */ protected void waitForServiceCallback(final ServiceCallback serviceCallback, final String requestId, long timeout) throws ServiceTimeoutException { if (serviceCallback == null) { return; } // wait from the response from the service long timeLimit = timeout; long sleepTime = 10l; long elapsedTime = 0; // the callback is done if a response or error is handled by the manager while (!serviceCallback.isDone()) { try { Thread.sleep(sleepTime); } catch (InterruptedException exception) { } // if the timeout is greater than zero then check for elapsed time if (timeLimit > 0l) { elapsedTime += sleepTime; if (elapsedTime >= timeLimit) { synchronized (this.requests) { this.requests.remove(requestId); } Object[] lparams = {requestId, "" + timeLimit}; String lmessage = LOGGER.error(SCCLMessageCode.MESSAGE_TIMEOUT_E.getMessageCode(), lparams); throw new ServiceTimeoutException(lmessage); } } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy