class ToolkitInstanceFactoryImpl implements ToolkitInstanceFactory {

  @Override
  public void clusterRejoined() {
    String cacheManagerName = entityNames.cacheManagerName;
    synchronized (entityNames) {
      ClusteredCacheManager clusteredCacheManager = clusteredEntityManager.getRootEntity(cacheManagerName,
                                                                                         ClusteredCacheManager.class);
      if (clusteredCacheManager == null) {
        LOGGER.error("Cache Manager {} has been destroyed by some other node - shutting down to prevent any further use of clustered features", cacheManagerName);
        shutdown();
      } else {
        // release Cache Manager lock after rejoin
        try {
          clusteredCacheManager.releaseUse();
        } catch (Exception e) {
          // Ignore - just trying to clean up
          LOGGER.trace("Exception trying to release cache manager {} after rejoin", entityNames.cacheManagerName);
        }

        // release cache read lock after rejoin
        for (String cacheName : entityNames.getCacheNames()) {
          ClusteredCache cacheEntity = clusteredCacheManagerEntity.getCache(cacheName);
          if (cacheEntity != null) {
            try {
              clusteredCacheManagerEntity.releaseCacheUse(cacheEntity);
            } catch (Exception e) {
              // Ignore - just trying to clean up
              LOGGER.trace("Exception trying to release cache {} after rejoin", cacheName);
            }
          }
        }

        int retryCount = 0;
        boolean success = false;
        while (retryCount < RETRY_MARK_IN_USE_AFTER_REJOIN) {
          // grab Cache Manager read lock after rejoin
          try {
            clusteredCacheManager.markInUse();
            success = (clusteredEntityManager.getRootEntity(cacheManagerName, ClusteredCacheManager.class) != null);
            break;
          } catch (Exception e) {
            try {
              TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e1) {
              // Do nothing
            }
            retryCount++;
          }
        }
        if (!success) {
          LOGGER.error("Unable to mark cache manager {} in use - shutting down to prevent any further use of clustered features", cacheManagerName);
          shutdown();
        } else {
          // grab cache read lock after rejoin
          for (String cacheName : entityNames.getCacheNames()) {
            boolean successCache = false;
            int retryCountCache = 0;
            while (!successCache && retryCountCache < RETRY_MARK_IN_USE_AFTER_REJOIN) {
              ClusteredCache cacheEntity = clusteredCacheManagerEntity.getCache(cacheName);
              if (cacheEntity == null) {
                LOGGER.error("Cache " + cacheName + " has been destroyed by some other node");
                successCache = true;
              } else {
                try {
                  clusteredCacheManagerEntity.markCacheInUse(cacheEntity);
                  successCache = true;
                } catch (Exception e) {
                  try {
                    TimeUnit.SECONDS.sleep(1);
                  } catch (InterruptedException e1) {
                    // Do nothing
                  }
                  retryCountCache++;
                }
              }
            }
          }
        }
      }
    }
  }

  public  ToolkitInstanceFactoryImpl(final TerracottaClientConfiguration terracottaClientConfiguration, final String productId);
  public  ToolkitInstanceFactoryImpl(final TerracottaClientConfiguration terracottaClientConfiguration);
    ToolkitInstanceFactoryImpl(final Toolkit toolkit, final ClusteredEntityManager clusteredEntityManager);
    ToolkitInstanceFactoryImpl(final Toolkit toolkit, final ClusteredEntityManager clusteredEntityManager,
                             final WANUtil util, final Watchdog wanWatchdog);

}