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.");
    }
  }