private void releaseLock() { try { if (lock.isAcquiredInThisProcess()) { lock.release(); } } catch (Exception e) { throw FabricException.launderThrowable(e); } }
private InterProcessLock getLock(String name) throws Exception { InterProcessLock lock = null; while (true) { try { lock = _coordinator.getSiteLocalLock(name); lock.acquire(); break; // got lock } catch (Exception e) { if (_coordinator.isConnected()) { throw e; } } } return lock; }
private void manageProfile(TaskContext context) { Container current = fabricService.get().getCurrentContainer(); ProfileData profileData = createProfileData(context); String profileId = context.getConfiguration().get(TEMPLATE_PROFILE_PROPERTY_NAME) + "-" + name; Version version = current.getVersion(); try { if (lock.acquire(60, TimeUnit.SECONDS)) { if (profileData.isEmpty()) { if (version.hasProfile(profileId)) { // Just delete the profile version.getProfile(profileId).delete(true); } return; } else if (!version.hasProfile(profileId)) { // Create the profile fabricService.get().getDataStore().createProfile(version.getId(), profileId); } Profile managedProfile = version.getProfile(profileId); // managedProfile.setConfigurations(profileData.getConfigs()); managedProfile.setFileConfigurations(profileData.getFiles()); current.addProfiles(managedProfile); } else { throw new TimeoutException("Timed out waiting for lock"); } } catch (Exception e) { LOGGER.error("Error managing work items.", e); } finally { 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; } }
/** * 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."); lock.acquire(); // will only throw exception or pass } 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; } }
@Override public void start() throws IOException { if (_log.isInfoEnabled()) { _log.info("Starting DB service..."); } // Suppress Sonar violation of Lazy initialization of static fields should be synchronized // start() method will be only called one time when startup dbsvc, so it's safe to ignore sonar // violation instance = this; // NOSONAR ("squid:S2444") if (backCompatPreYoda) { _log.info( "Pre-yoda back compatible flag detected. Initialize local keystore/truststore for Cassandra native encryption"); initKeystoreAndTruststore(); _schemaUtil.setBackCompatPreYoda(true); } System.setProperty("cassandra.config", _config); System.setProperty("cassandra.config.loader", CassandraConfigLoader.class.getName()); // Set to false to clear all gossip state for the node on restart. // // We encounter a weird Cassandra grossip issue(COP-19246) - some nodes are missing from gossip // when rebooting the entire cluster simultaneously. Critical Gossip // fields(ApplicationState.STATUS, ApplicationState.TOKENS) // are not synchronized during handshaking. It looks like some problem caused by incorrect // gossip version/generation // at system local table. So add this option to cleanup local gossip state during reboot // // Make sure add-vdc/add-standby passed when you would remove this option in the future. // // We need make sure majority local nodes are added as seed nodes. Otherwise cassandra may not // see other nodes if it loses // connection to other sites System.setProperty("cassandra.load_ring_state", "false"); // Nodes in new data center should not auto-bootstrap. // See // https://docs.datastax.com/en/cassandra/2.0/cassandra/operations/ops_add_dc_to_cluster_t.html if (_schemaUtil.isStandby()) { System.setProperty("cassandra.auto_bootstrap", "false"); } InterProcessLock lock = null; Configuration config = null; StartupMode mode = null; try { // we use this lock to discourage more than one node bootstrapping / joining at the same time // Cassandra can handle this but it's generally not recommended to make changes to schema // concurrently lock = getLock(getSchemaLockName()); config = checkConfiguration(); checkGlobalConfiguration(); checkVersionedConfiguration(); removeStaleConfiguration(); mode = checkStartupMode(config); _log.info("Current startup mode is {}", mode); // Check if service is allowed to get started by querying db offline info to avoid bringing // back stale data. // Skipping hibernate mode for node recovery procedure to recover the overdue node. int nodeCount = ((CoordinatorClientImpl) _coordinator).getNodeCount(); if (nodeCount != 1 && mode.type != StartupMode.StartupModeType.HIBERNATE_MODE) { checkDBOfflineInfo(); } // this call causes instantiation of a seed provider instance, so the check*Configuration // calls must be preceed it removeCassandraSavedCaches(); mode.onPreStart(); if (_jmxServer != null) { _jmxServer.start(); System.setProperty( "com.sun.management.jmxremote.port", Integer.toString(_jmxServer.getPort())); } _service = new CassandraDaemon(); _service.init(null); _service.start(); cassandraInitialized = true; mode.onPostStart(); } catch (Exception e) { if (mode != null && mode.type == StartupMode.StartupModeType.HIBERNATE_MODE) { printRecoveryWorkAround(e); } _log.error("e=", e); throw new IllegalStateException(e); } finally { if (lock != null) { try { lock.release(); } catch (Exception ignore) { _log.debug("lock release failed"); } } } if (config.getConfig(DbConfigConstants.JOINED) == null) { config.setConfig(DbConfigConstants.JOINED, Boolean.TRUE.toString()); _coordinator.persistServiceConfiguration(_coordinator.getSiteId(), config); } _statusChecker.waitForAllNodesJoined(); _svcBeacon.start(); if (backCompatPreYoda) { _log.info("Enable duplicated beacon in global area during pre-yoda upgrade"); startDupBeacon(); } setDbInitializedFlag(); setDbConfigInitDone(); _dbClient.start(); if (_schemaUtil.isStandby()) { String localDataRevision = getLocalDataRevision(); if (localDataRevision != null) { _schemaUtil.checkDataRevision(localDataRevision); } } // Setup the vdc information, so that login enabled before migration if (!isGeoDbsvc()) { _schemaUtil.checkAndSetupBootStrapInfo(_dbClient); } dbMgr.init(); if (_handler.run()) { // Setup the bootstrap info root tenant, if root tenant migrated from local db, then skip it if (isGeoDbsvc()) { _schemaUtil.checkAndSetupBootStrapInfo(_dbClient); } else { _schemaUtil.checkAndInitStorageSystemTypes(_dbClient); } startBackgroundTasks(); _log.info("DB service started"); } else { _log.error("DB migration failed. Skipping starting background tasks."); } }