GfErrType LocalRegion::destroyRegionNoThrow()

in cppcache/src/LocalRegion.cpp [2355:2469]


GfErrType LocalRegion::destroyRegionNoThrow(
    const std::shared_ptr<Serializable>& aCallbackArgument,
    bool removeFromParent, const CacheEventFlags eventFlags) {
  // Get global locks to synchronize with failover thread.
  // TODO:  This should go into RegionGlobalLocks
  // The distMngrsLock is required before RegionGlobalLocks since failover
  // thread acquires distMngrsLock and then tries to acquire endpoints lock
  // which is already taken by RegionGlobalLocks here.
  DistManagersLockGuard _guard(m_cacheImpl->tcrConnectionManager());
  RegionGlobalLocks acquireLocks(this);

  // Fix for BUG:849, i.e Remove subscription on region before destroying the
  // region
  if (eventFlags == CacheEventFlags::LOCAL) {
    if (unregisterKeysBeforeDestroyRegion() != GF_NOERR) {
      LOGDEBUG(
          "DEBUG :: LocalRegion::destroyRegionNoThrow UnregisteredKeys "
          "Failed");
    }
  }

  boost::unique_lock<decltype(mutex_)> guard{mutex_};
  if (m_destroyPending) {
    if (eventFlags.isCacheClose()) {
      return GF_NOERR;
    } else {
      return GF_CACHE_REGION_DESTROYED_EXCEPTION;
    }
  }

  m_destroyPending = true;
  LOGDEBUG("LocalRegion::destroyRegionNoThrow( ): set flag destroy-pending.");

  GfErrType err = GF_NOERR;

  //  do not invoke the writer for expiry or notification
  if (!eventFlags.isNotification() && !eventFlags.isEvictOrExpire()) {
    if (!invokeCacheWriterForRegionEvent(aCallbackArgument, eventFlags,
                                         BEFORE_REGION_DESTROY)) {
      //  do not let CacheWriter veto when this is Cache::close()
      if (!eventFlags.isCacheClose()) {
        LOGFINE("Cache writer prevented region destroy");
        m_destroyPending = false;
        return GF_CACHEWRITER_ERROR;
      }
    }
    //  for the expiry case try the local destroy first and remote
    // destroy only if local destroy succeeds
    if (!eventFlags.isLocal()) {
      err = destroyRegionNoThrow_remote(aCallbackArgument);
      if (err != GF_NOERR) {
        m_destroyPending = false;
        return err;
      }
    }
  }

  LOGFINE("Region %s is being destroyed", m_fullPath.c_str());
  {
    auto&& lock = m_subRegions.make_lock();

    for (const auto& kv : m_subRegions) {
      // TODO: remove unnecessary dynamic_cast by having m_subRegions hold
      // RegionInternal and invoke the destroy method in that
      if (auto subRegion =
              std::dynamic_pointer_cast<RegionInternal>(kv.second)) {
        // for subregions never remove from parent since that will cause
        // the region to be destroyed and SEGV; unbind_all takes care of that
        // Also don't send remote destroy message for sub-regions
        err = subRegion->destroyRegionNoThrow(
            aCallbackArgument, false, eventFlags | CacheEventFlags::LOCAL);
        //  for Cache::close() keep going as far as possible
        if (err != GF_NOERR && !eventFlags.isCacheClose()) {
          m_destroyPending = false;
          return err;
        }
      }
    }
  }
  m_subRegions.clear();

  //  for the expiry case try the local destroy first and remote
  // destroy only if local destroy succeeds
  if (eventFlags.isEvictOrExpire() && !eventFlags.isLocal()) {
    err = destroyRegionNoThrow_remote(aCallbackArgument);
    if (err != GF_NOERR) {
      m_destroyPending = false;
      return err;
    }
  }
  //  if we are not removing from parent then this is a proper
  // region close so invoke listener->close() also
  err = invokeCacheListenerForRegionEvent(aCallbackArgument, eventFlags,
                                          AFTER_REGION_DESTROY);

  release(true);
  if (m_regionAttributes.getCachingEnabled()) {
    _GEODE_SAFE_DELETE(m_entries);
  }

  if (removeFromParent) {
    if (m_parentRegion == nullptr) {
      m_cacheImpl->removeRegion(m_name.c_str());
    } else {
      LocalRegion* parent = dynamic_cast<LocalRegion*>(m_parentRegion.get());
      if (parent != nullptr) {
        parent->removeRegion(m_name);
        if (!eventFlags.isEvictOrExpire()) {
          parent->updateAccessAndModifiedTime(true);
        }
      }
    }
  }
  return err;
}