Search in sources :

Example 1 with InterProcessLockHolder

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.");
    }
}
Also used : VirtualArray(com.emc.storageos.db.client.model.VirtualArray) Volume(com.emc.storageos.db.client.model.Volume) RPRecommendation(com.emc.storageos.volumecontroller.RPRecommendation) InterProcessLockHolder(com.emc.storageos.coordinator.client.service.InterProcessLockHolder) AlternateIdConstraint(com.emc.storageos.db.client.constraint.AlternateIdConstraint)

Example 2 with InterProcessLockHolder

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);
    }
}
Also used : InterProcessLockHolder(com.emc.storageos.coordinator.client.service.InterProcessLockHolder) ListenerNotFoundException(javax.management.ListenerNotFoundException) IOException(java.io.IOException) ListenerNotFoundException(javax.management.ListenerNotFoundException)

Aggregations

InterProcessLockHolder (com.emc.storageos.coordinator.client.service.InterProcessLockHolder)2 AlternateIdConstraint (com.emc.storageos.db.client.constraint.AlternateIdConstraint)1 VirtualArray (com.emc.storageos.db.client.model.VirtualArray)1 Volume (com.emc.storageos.db.client.model.Volume)1 RPRecommendation (com.emc.storageos.volumecontroller.RPRecommendation)1 IOException (java.io.IOException)1 ListenerNotFoundException (javax.management.ListenerNotFoundException)1