/*
* Copyright (c) 2012 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.api.service.impl.resource.utils;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.db.client.DbClient;
import com.emc.storageos.db.client.model.DataObject;
import com.emc.storageos.db.client.model.Operation;
import com.emc.storageos.db.common.DbDependencyPurger;
public class PurgeRunnable<T extends DataObject> implements Runnable {
private static final Logger _log = LoggerFactory.getLogger(PurgeRunnable.class);
private DbDependencyPurger _dbPurger;
private DbClient _dbClient;
private T _decommissionResouce;
private int _max_retries;
private ScheduledExecutorService _service;
private String _taskId;
private int _timeout;
// volatile int should be sufficient
// since it is guaranteed that multiple threads won't access it at the same time.
private volatile int _iteration = 1;
PurgeRunnable(DbClient dbClient, DbDependencyPurger purger,
ScheduledExecutorService executorService,
T resource, int maxIter, String taskId, int timeout) {
_dbClient = dbClient;
_dbPurger = purger;
_service = executorService;
_decommissionResouce = resource;
_max_retries = maxIter;
_taskId = taskId;
_timeout = timeout;
}
public void run() {
try {
_dbPurger.purge(_decommissionResouce.getId(), _decommissionResouce.getClass());
_log.info(String.format("Purged the database successfully with %d iterations: resource %s",
_iteration, _decommissionResouce.getId()));
Operation upd = new Operation(Operation.Status.ready.toString(),
String.format("Purged the resources %s from the Database", _decommissionResouce.getId()));
_dbClient.updateTaskOpStatus(_decommissionResouce.getClass(), _decommissionResouce.getId(), _taskId, upd);
} catch (Exception ex) {
_log.error(String.format("Failed to purge the database: resource %s, attempt #%d,",
_decommissionResouce.getId(), _iteration), ex);
if (_iteration == _max_retries) {
Operation op = new Operation(Operation.Status.error.toString(),
String.format("Failed to remove resource %s from the Database", _decommissionResouce.getId()));
_dbClient.updateTaskOpStatus(_decommissionResouce.getClass(), _decommissionResouce.getId(), _taskId, op);
} else {
try {
_iteration++;
_service.schedule(this, _timeout, TimeUnit.SECONDS);
} catch (Exception e) {
_log.error(String.format("Failed to reschedule removal of the resource %s from the database",
_decommissionResouce.getId()), e);
Operation op = new Operation(Operation.Status.error.toString(),
String.format("Failed to reschedule removal of the resource %s from the Database", _decommissionResouce.getId()));
_dbClient.updateTaskOpStatus(_decommissionResouce.getClass(), _decommissionResouce.getId(), _taskId, op);
}
}
}
}
/**
* Execute Database purging for the given resource by using provided Executor service.
* If the first attempt to purge fails, the method would attempt to run the task maxIter
* number of times with "timeout" delay between consequent attempts.
* The provided "purger" should find all the children of the resource and deactivate them
* in the database.
*
* @param dbClient
* @param purger
* @param executorService
* @param resource
* @param maxIter
* @param taskId
* @param timeout
* @param <T>
*/
public static <T extends DataObject> void executePurging(DbClient dbClient,
DbDependencyPurger purger,
ScheduledExecutorService executorService,
T resource,
int maxIter,
String taskId,
int timeout) {
PurgeRunnable<T> purgeRunner = new PurgeRunnable<T>(dbClient, purger,
executorService, resource,
maxIter, taskId, timeout);
try {
executorService.execute(purgeRunner);
} catch (Exception e) {
_log.error(String.format("Failed to reschedule removal of the resource %s from the database",
resource.getId()), e);
Operation op = new Operation(Operation.Status.error.toString(),
String.format("Failed to schedule removal of the resource %s rom the Database",
resource.getId()));
dbClient.updateTaskOpStatus(resource.getClass(), resource.getId(), taskId, op);
}
}
}