use of com.emc.storageos.coordinator.client.service.InterProcessLockHolder in project coprhd-controller by CoprHD.
the class RPBlockServiceApiImpl method prepareRpJournals.
/**
* Prepares all the journal volumes and populates the values into the sourceJournals and/or
* the targetJournals map.
*
* @param rpProtectionRec
* - The main rec object
* @param project
* - The project
* @param consistencyGroup
* - The CG
* @param vpool
* - The vpool (potentially swapped)
* @param originalVpool
* - The original vpool
* @param param
* - Volume create param
* @param numberOfVolumesInRequest
* - Number of volumes to create
* @param newVolumeLabel
* - Label of volume
* @param isChangeVpoolForProtectedVolume
* - Flag for protected change vpool op
* @param capabilities
* - Capabilities object
* @param protectionSystemURI
* - Protection System being used
* @param taskList
* - Task List
* @param task
* - Task
* @param descriptors
* - List of all descriptors to be added
* @param volumeURIs
* - List to store all the volume URIs
* @param volumeInfoBuffer
* - Buffer for volume info to be printed
* @param sourceCopyName
* - Source Copy Name
* @param standbySourceCopyName
* - Standby Copy Name
*/
private void prepareRpJournals(RPProtectionRecommendation rpProtectionRec, Project project, BlockConsistencyGroup consistencyGroup, VirtualPool vpool, VirtualPool originalVpool, VolumeCreate param, Integer numberOfVolumesInRequest, String newVolumeLabel, boolean isChangeVpoolForProtectedVolume, VirtualPoolCapabilityValuesWrapper capabilities, URI protectionSystemURI, TaskList taskList, String task, List<VolumeDescriptor> descriptors, List<URI> volumeURIs, StringBuffer volumeInfoBuffer, String sourceCopyName, String standbySourceCopyName) throws Exception {
Volume sourceJournal = null;
Volume standbyJournal = null;
// This boolean indicates that the operation is only for adding additional journals.
// When adding additional journals, there is the option to add multiple new journals,
// however, for all other creates we are either re-using an existing journal or
// just creating a single journal.
// i.e. the majority of the time we are only creating a single journal.
boolean journalOnlyCreate = capabilities.getAddJournalCapacity();
RPRecommendation sourceJournalRec = rpProtectionRec.getSourceJournalRecommendation();
RPRecommendation standbyJournalRec = rpProtectionRec.getStandbyJournalRecommendation();
// Only check for existing source journals if this is not a direct journal add operation.
if (!journalOnlyCreate) {
if (sourceJournalRec == null) {
_log.info(String.format("Re-use existing Source Journal for copy [%s]", sourceCopyName));
// If the CG contains volumes already and no new additional journals are provisioned,
// then we simply update the reference on the source for the journal volume.
List<Volume> existingSourceJournals = RPHelper.findExistingJournalsForCopy(_dbClient, consistencyGroup.getId(), sourceCopyName);
sourceJournal = existingSourceJournals.get(0);
_log.info(String.format("Existing Primary Source Journal: [%s] (%s)", sourceJournal.getLabel(), sourceJournal.getId()));
if (VirtualPool.vPoolSpecifiesMetroPoint(vpool) && !isChangeVpoolForProtectedVolume) {
_log.info(String.format("Re-use existing Standby Journal for copy [%s]", standbySourceCopyName));
List<Volume> existingStandbyJournals = RPHelper.findExistingJournalsForCopy(_dbClient, consistencyGroup.getId(), standbySourceCopyName);
standbyJournal = existingStandbyJournals.get(0);
_log.info(String.format("Existing Standby Source Journal: [%s] (%s)", standbyJournal.getLabel(), standbyJournal.getId()));
}
}
}
// /////// ACTIVE SOURCE JOURNAL ///////////
if (!isChangeVpoolForProtectedVolume && (sourceJournal == null) && sourceJournalRec != null) {
_log.info("Create Active Source Journal...");
// varray is used to get unique journal volume names
VirtualArray varray = _dbClient.queryObject(VirtualArray.class, sourceJournalRec.getVirtualArray());
// Number of journals to create
int numberOfJournalVolumesInRequest = sourceJournalRec.getResourceCount();
// Force resource count to 1 here because we're using numberOfJournalVolumesInRequest to create the
// correct number of journal resources.
sourceJournalRec.setResourceCount(1);
for (int volumeCount = 0; volumeCount < numberOfJournalVolumesInRequest; volumeCount++) {
// acquire a lock so it's possible to get a unique name for the volume
String lockKey = new StringBuilder(consistencyGroup.getLabel()).append("-").append(varray.getLabel()).toString();
InterProcessLockHolder lock = null;
try {
_log.info("Attempting to acquire lock: " + lockKey);
lock = InterProcessLockHolder.acquire(_coordinator, lockKey, _log, LOCK_WAIT_MILLISECONDS);
// get a unique journal volume name
String journalName = RPHelper.createJournalVolumeName(varray, consistencyGroup, _dbClient);
// Create source journal
sourceJournal = createRecoverPointVolume(sourceJournalRec, journalName, project, capabilities, consistencyGroup, param, protectionSystemURI, Volume.PersonalityTypes.METADATA, JOURNAL_RSET, null, null, taskList, task, sourceCopyName, descriptors, null, false, false, true);
} finally {
if (lock != null) {
lock.close();
}
}
volumeURIs.add(sourceJournal.getId());
volumeInfoBuffer.append(logVolumeInfo(sourceJournal));
}
}
// /////// STANDBY SOURCE JOURNAL ///////////
if (standbyJournal == null && standbyJournalRec != null) {
_log.info("Create Standby Source Journal...");
// varray is used to get unique journal volume names
VirtualArray varray = _dbClient.queryObject(VirtualArray.class, standbyJournalRec.getVirtualArray());
// Number of journals to create
int numberOfJournalVolumesInRequest = standbyJournalRec.getResourceCount();
// Force resource count to 1 here because we're using numberOfJournalVolumesInRequest to create the
// correct number of journal resources.
standbyJournalRec.setResourceCount(1);
for (int volumeCount = 0; volumeCount < numberOfJournalVolumesInRequest; volumeCount++) {
// acquire a lock so it's possible to get a unique name for the volume
String lockKey = new StringBuilder(consistencyGroup.getLabel()).append("-").append(varray.getLabel()).toString();
InterProcessLockHolder lock = null;
try {
_log.info("Attempting to acquire lock: " + lockKey);
lock = InterProcessLockHolder.acquire(_coordinator, lockKey, _log, LOCK_WAIT_MILLISECONDS);
// get a unique journal volume name
String journalName = RPHelper.createJournalVolumeName(varray, consistencyGroup, _dbClient);
// If MetroPoint is enabled we need to create the standby journal volume
standbyJournal = createRecoverPointVolume(standbyJournalRec, journalName, project, capabilities, consistencyGroup, param, protectionSystemURI, Volume.PersonalityTypes.METADATA, JOURNAL_RSET, null, null, taskList, task, standbySourceCopyName, descriptors, null, false, false, true);
} finally {
if (lock != null) {
lock.close();
}
}
volumeURIs.add(standbyJournal.getId());
volumeInfoBuffer.append(logVolumeInfo(standbyJournal));
}
}
// /////// TARGET JOURNAL(s) ///////////
if (!isChangeVpoolForProtectedVolume && rpProtectionRec.getTargetJournalRecommendations() != null && !rpProtectionRec.getTargetJournalRecommendations().isEmpty()) {
for (RPRecommendation targetJournalRec : rpProtectionRec.getTargetJournalRecommendations()) {
VirtualArray targetJournalVarray = _dbClient.queryObject(VirtualArray.class, targetJournalRec.getVirtualArray());
// This is the varray for the target we're associating the journal too. It could be the case
// that it is the same as the target journal varray set, or the user could have chosen a different
// varray for their target journal in which case we do need to find which target/copy this journal will
// be associated to in the RP CG.
// Ex:
// Target varray1
// Target journal varray6
// The target journal is varray6, however we are adding the journal to the target copy based on the protection
// settings defined for varray1.
VirtualArray targetCopyVarray = getProtectionVarray(rpProtectionRec, targetJournalRec.getInternalSiteName());
if (targetCopyVarray == null) {
targetCopyVarray = targetJournalVarray;
}
_log.info(String.format("Create Target Journal (%s)...", targetJournalVarray.getLabel()));
// Number of journals to create
int numberOfJournalVolumesInRequest = targetJournalRec.getResourceCount();
// Force resource count to 1 here because we're using numberOfJournalVolumesInRequest to create the
// correct number of journal resources.
targetJournalRec.setResourceCount(1);
for (int volumeCount = 0; volumeCount < numberOfJournalVolumesInRequest; volumeCount++) {
// acquire a lock so it's possible to get a unique name for the volume
String lockKey = new StringBuilder(consistencyGroup.getLabel()).append("-").append(targetCopyVarray.getLabel()).toString();
InterProcessLockHolder lock = null;
try {
_log.info("Attempting to acquire lock: " + lockKey);
lock = InterProcessLockHolder.acquire(_coordinator, lockKey, _log, LOCK_WAIT_MILLISECONDS);
// get a unique journal volume name
String journalName = RPHelper.createJournalVolumeName(targetCopyVarray, consistencyGroup, _dbClient);
// Create target journal
Volume targetJournalVolume = createRecoverPointVolume(targetJournalRec, journalName, project, capabilities, consistencyGroup, param, protectionSystemURI, Volume.PersonalityTypes.METADATA, JOURNAL_RSET, null, null, taskList, task, targetJournalRec.getRpCopyName(), descriptors, null, false, false, false);
volumeURIs.add(targetJournalVolume.getId());
volumeInfoBuffer.append(logVolumeInfo(targetJournalVolume));
} finally {
if (lock != null) {
lock.close();
}
}
}
}
} else {
_log.info("Re-use existing Target journals.");
}
}
use of com.emc.storageos.coordinator.client.service.InterProcessLockHolder in project coprhd-controller by CoprHD.
the class DbRepairRunnable method run.
@Override
public void run() {
try (ScopeNotifier notifier = new ScopeNotifier(this)) {
log.info("prepare db repair");
// use same lock:DB_REPAIR_LOCK for both local/geo db to ensure db repair sequentially
try (InterProcessLockHolder holder = new InterProcessLockHolder(this.coordinator, DB_REPAIR_LOCK, log)) {
log.info("get {} lock, start to do db repair", DB_REPAIR_LOCK);
this.status = getRepairStatus(holder.getLock());
if (this.status != StartStatus.STARTED) {
return;
}
try (RepairJobRunner runner = createJobRunner(jmxServer)) {
// Save state to ZK before notify caller to return so it will see the result of call.
saveStates();
log.info("Repair started, notifying the triggering thread to return.");
// Notify the thread triggering the repair before we finish
notifier.close();
int repairDelay = 0;
while (true) {
ScheduledFuture<Boolean> repairTask = executor.schedule(new Callable<Boolean>() {
@Override
public Boolean call() {
boolean needRetry = false;
try {
RepairJobRunner.RepairJobStatus repairJobStatus = runner.runRepair();
needRetry = checkRepairStatus(repairJobStatus);
} catch (IOException | InterruptedException ex) {
log.error("Repair job failed with exception", ex);
}
return needRetry;
}
}, repairDelay, TimeUnit.MINUTES);
while (!repairTask.isDone()) {
log.debug("Waiting repair task finish...");
Thread.sleep(60 * 1000L);
}
log.info("Repair need retry: {}", repairTask.get());
if (!repairTask.get()) {
break;
}
repairDelay = repairRetryMin;
}
} catch (ListenerNotFoundException ex) {
this.threadException = ex;
log.error("Failed to remove notification listener", ex);
}
} catch (Exception ex) {
this.threadException = ex;
log.error("Exception starting", ex);
}
} catch (Exception ex) {
this.threadException = ex;
log.error("Exception starting", ex);
}
}
Aggregations