use of org.apache.curator.framework.recipes.locks.InterProcessLock in project coprhd-controller by CoprHD.
the class DataCollectionJobConsumer method triggerScanning.
/**
* 1. refreshConnections - needs to get called on each Controller, before acquiring lock.
* 2. Try to acquire lock, if found
* 3. Acquiring lock is not made as a Blocking Call, hence Controllers will return immediately,
* if lock not found
* 3. If lock found, spawn a new thread to do triggerScanning.
* 4. Release lock immediately.
*/
private void triggerScanning(DataCollectionScanJob job) throws Exception {
_logger.info("Started scanning Providers : triggerScanning()");
List<URI> providerList = job.getProviders();
String providerType = null;
if (!providerList.isEmpty()) {
providerType = _dbClient.queryObject(StorageProvider.class, providerList.iterator().next()).getInterfaceType();
}
_jobScheduler.refreshProviderConnections(providerType);
List<URI> allProviderURI = _dbClient.queryByType(StorageProvider.class, true);
List<StorageProvider> allProvidersAllTypes = _dbClient.queryObject(StorageProvider.class, allProviderURI);
List<StorageProvider> allProviders = new ArrayList<StorageProvider>();
// since dbQuery does not return a normal list required by bookkeeping, we need to rebuild it.
allProviderURI = new ArrayList<URI>();
for (StorageProvider provider : allProvidersAllTypes) {
if (providerType == null || providerType.equals(provider.getInterfaceType())) {
allProviderURI.add(provider.getId());
allProviders.add(provider);
}
}
Map<String, StorageSystemViewObject> storageSystemsCache = Collections.synchronizedMap(new HashMap<String, StorageSystemViewObject>());
boolean exceptionIntercepted = false;
/**
* Run "Scheduled" Scanner Jobs of all Providers in only one Controller.
* means our Cache is populated with the latest
* physicalStorageSystems ID got from this scheduled Scan Job.
* Compare the list against the ones in DB, and decide the physicalStorageSystem's
* state REACHABLE
*/
String lockKey = ControllerServiceImpl.Lock.SCAN_COLLECTION_LOCK.toString();
if (providerType != null) {
lockKey += providerType;
}
InterProcessLock scanLock = _coordinator.getLock(lockKey);
if (scanLock.acquire(ControllerServiceImpl.Lock.SCAN_COLLECTION_LOCK.getRecommendedTimeout(), TimeUnit.SECONDS)) {
_logger.info("Acquired a lock {} to run scanning Job", ControllerServiceImpl.Lock.SCAN_COLLECTION_LOCK.toString() + providerType);
List<URI> cacheProviders = new ArrayList<URI>();
Map<URI, Exception> cacheErrorProviders = new HashMap<URI, Exception>();
try {
boolean scanIsNeeded = false;
boolean hasProviders = false;
// First find out if scan is needed. If it needed for a single system , it is needed for all
for (StorageProvider provider : allProviders) {
if (provider.connected() || provider.initializing()) {
hasProviders = true;
if (_jobScheduler.isProviderScanJobSchedulingNeeded(provider, ControllerServiceImpl.SCANNER, job.isSchedulerJob())) {
scanIsNeeded = true;
break;
}
}
}
if (!scanIsNeeded) {
for (StorageProvider provider : allProviders) {
ScanTaskCompleter scanCompleter = job.findProviderTaskCompleter(provider.getId());
if (scanCompleter == null) {
continue;
}
if (provider.connected() || provider.initializing()) {
scanCompleter.ready(_dbClient);
} else {
String errMsg = "Failed to establish connection to the storage provider";
scanCompleter.error(_dbClient, DeviceControllerErrors.smis.unableToCallStorageProvider(errMsg));
provider.setLastScanStatusMessage(errMsg);
_dbClient.updateObject(provider);
}
}
if (!hasProviders) {
_util.performBookKeeping(storageSystemsCache, allProviderURI);
}
_logger.info("Scan is not needed");
} else {
// If scan is needed for a single system,
// it must be performed for all available providers in the database at the same time.
// update each provider that is reachable to scan in progress
List<StorageProvider> connectedProviders = new ArrayList<StorageProvider>();
for (StorageProvider provider : allProviders) {
if (provider.connected() || provider.initializing()) {
ScanTaskCompleter scanCompleter = job.findProviderTaskCompleter(provider.getId());
if (scanCompleter == null) {
String taskId = UUID.randomUUID().toString();
scanCompleter = new ScanTaskCompleter(StorageProvider.class, provider.getId(), taskId);
job.addCompleter(scanCompleter);
}
scanCompleter.createDefaultOperation(_dbClient);
scanCompleter.updateObjectState(_dbClient, DiscoveredDataObject.DataCollectionJobStatus.IN_PROGRESS);
scanCompleter.setNextRunTime(_dbClient, System.currentTimeMillis() + DataCollectionJobScheduler.JobIntervals.get(ControllerServiceImpl.SCANNER).getInterval() * 1000);
provider.setLastScanStatusMessage("");
_dbClient.updateObject(provider);
connectedProviders.add(provider);
} else {
if (null != provider.getStorageSystems() && !provider.getStorageSystems().isEmpty()) {
provider.getStorageSystems().clear();
}
if (providerList.contains(provider.getId())) {
String errMsg = "Failed to establish connection to the storage provider";
provider.setLastScanStatusMessage(errMsg);
job.findProviderTaskCompleter(provider.getId()).error(_dbClient, DeviceControllerErrors.smis.unableToCallStorageProvider(errMsg));
}
_dbClient.updateObject(provider);
}
}
// now scan each connected provider
for (StorageProvider provider : connectedProviders) {
try {
_logger.info("provider.getInterfaceType():{}", provider.getInterfaceType());
ScanTaskCompleter scanCompleter = job.findProviderTaskCompleter(provider.getId());
performScan(provider.getId(), scanCompleter, storageSystemsCache);
cacheProviders.add(provider.getId());
} catch (Exception ex) {
_logger.error("Scan failed for {}--->", provider.getId(), ex);
cacheErrorProviders.put(provider.getId(), ex);
}
}
// Perform BooKKeeping
// TODO: we need to access the status of job completer.
// for now we assume that this operation can not fail.
_util.performBookKeeping(storageSystemsCache, allProviderURI);
}
} catch (final Exception ex) {
_logger.error("Scan failed for {} ", ex.getMessage());
exceptionIntercepted = true;
for (URI provider : cacheProviders) {
job.findProviderTaskCompleter(provider).error(_dbClient, DeviceControllerErrors.dataCollectionErrors.scanFailed(ex.getLocalizedMessage(), ex));
_logger.error("Scan failed for {}--->", provider, ex);
}
throw ex;
} finally {
if (!exceptionIntercepted) {
for (URI provider : cacheProviders) {
job.findProviderTaskCompleter(provider).ready(_dbClient);
_logger.info("Scan complete successfully for " + provider);
}
}
for (Entry<URI, Exception> entry : cacheErrorProviders.entrySet()) {
URI provider = entry.getKey();
Exception ex = entry.getValue();
job.findProviderTaskCompleter(provider).error(_dbClient, DeviceControllerErrors.dataCollectionErrors.scanFailed(ex.getLocalizedMessage(), ex));
}
scanLock.release();
_logger.info("Released a lock {} to run scanning Job", lockKey);
try {
if (!exceptionIntercepted) /* && job.isSchedulerJob() */
{
// Manually trigger discoveries, if any new Arrays detected
triggerDiscoveryNew(storageSystemsCache, (job.isSchedulerJob() ? DataCollectionJob.JobOrigin.SCHEDULER : DataCollectionJob.JobOrigin.USER_API));
}
} catch (Exception ex) {
_logger.error("Exception occurred while triggering discovery of new systems", ex);
}
}
} else {
job.setTaskError(_dbClient, DeviceControllerErrors.dataCollectionErrors.scanLockFailed());
_logger.error("Not able to Acquire Scanning {} lock-->{}", lockKey, Thread.currentThread().getId());
}
}
use of org.apache.curator.framework.recipes.locks.InterProcessLock in project coprhd-controller by CoprHD.
the class VPlexApiLockManager method acquireLock.
/**
* Attempts to acquire the passed lock.
*
* @param lockName The name of the lock to acquire.
* @param waitInSeconds The amount of time to wait to acquire the lock in
* seconds. A value less than 0 will cause the function
* to wait indefinitely for the lock.
*
* @return true if lock acquired, false otherwise.
*/
public boolean acquireLock(String lockName, long waitInSeconds) {
if (lockName == null || lockName.isEmpty()) {
s_logger.info("No lock name specified.");
return false;
}
try {
InterProcessLock lock = _coordinator.getLock(lockName);
if (lock != null) {
if (waitInSeconds >= 0) {
s_logger.info("Attempting to acquire lock: " + lockName + " for a maximum of " + waitInSeconds + " seconds.");
if (!lock.acquire(waitInSeconds, TimeUnit.SECONDS)) {
s_logger.info("Failed to acquire lock: " + lockName);
return false;
}
} else {
s_logger.info("Attempting to acquire lock: " + lockName + " for as long as it takes.");
// will only throw exception or pass
lock.acquire();
}
s_acquiredLocks.put(lockName, lock);
} else {
return false;
}
s_logger.info("Acquired lock: " + lockName);
return true;
} catch (Exception e) {
s_logger.error("Acquisition of lock: {} failed with Exception: ", lockName, e);
return false;
}
}
use of org.apache.curator.framework.recipes.locks.InterProcessLock in project coprhd-controller by CoprHD.
the class VPlexApiLockManager method releaseLock.
/**
* Release the passed lock.
*
* @param lockName The name of the lock to release.
*
* @return true if the lock is released, false otherwise.
*/
public boolean releaseLock(String lockName) {
if (lockName == null || lockName.isEmpty()) {
s_logger.info("No lock name specified.");
return false;
}
try {
InterProcessLock lock = s_acquiredLocks.get(lockName);
if (lock != null) {
s_acquiredLocks.remove(lockName);
lock.release();
s_logger.info("Released lock: " + lockName);
} else {
return false;
}
return true;
} catch (Exception e) {
s_logger.error("Release of lock: {} failed with Exception: ", lockName, e);
return false;
}
}
use of org.apache.curator.framework.recipes.locks.InterProcessLock in project coprhd-controller by CoprHD.
the class GarbageCollectionExecutorLoop method getLockForGC.
private InterProcessLock getLockForGC() {
InterProcessLock lock = null;
String lockName = getGCZKLockName();
try {
log.info("try to get ZK GC lock {}", lockName);
lock = coordinator.getLock(lockName);
if (!lock.acquire(0, TimeUnit.SECONDS)) {
// try to get the lock timeout=0
log.info("Can't get ZK lock for GC");
// failed to get the lock
return null;
}
log.info("Get GC lock {}", lockName);
} catch (Exception e) {
log.warn("Failed to acquire lock for GC {} Exception e=", lockName, e);
lock = null;
}
return lock;
}
use of org.apache.curator.framework.recipes.locks.InterProcessLock in project coprhd-controller by CoprHD.
the class DbManager method getLastRepairStatus.
@Override
public DbRepairStatus getLastRepairStatus(boolean forCurrentNodesOnly) {
try {
DbRepairJobState state = DbRepairRunnable.queryRepairState(this.coordinator, this.schemaUtil.getKeyspaceName(), this.schemaUtil.isGeoDbsvc());
log.info("cluster state digest stored in ZK: {}", state.getCurrentDigest());
DbRepairStatus retState = getLastRepairStatus(state, forCurrentNodesOnly ? DbRepairRunnable.getClusterStateDigest() : null, this.repairRetryTimes);
if (retState != null && retState.getStatus() == DbRepairStatus.Status.IN_PROGRESS) {
// See if current state holder is still active, if not, we need to resume it
String lockName = DbRepairRunnable.getLockName();
InterProcessLock lock = coordinator.getLock(lockName);
String currentHolder = DbRepairRunnable.getSelfLockNodeId(lock);
if (currentHolder == null) {
// No thread is actually driving the repair, we need to resume it
if (startNodeRepair(this.schemaUtil.getKeyspaceName(), this.repairRetryTimes, false, true)) {
log.info("Successfully resumed a previously paused repair");
} else {
log.warn("Cannot resume a previously paused repair, it could be another thread resumed and finished it");
}
}
}
return retState;
} catch (Exception e) {
log.error("Failed to get node repair state from ZK", e);
return null;
}
}
Aggregations