All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.terracotta.entity.ClusteredEntityManager Maven / Gradle / Ivy

Go to download

Ehcache is an open source, standards-based cache used to boost performance, offload the database and simplify scalability. Ehcache is robust, proven and full-featured and this has made it the most widely-used Java-based cache.

There is a newer version: 2.10.9.2
Show newest version
/*
 * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved.
 */
package com.terracotta.entity;

import org.terracotta.toolkit.Toolkit;
import org.terracotta.toolkit.collections.ToolkitMap;
import org.terracotta.toolkit.concurrent.locks.ToolkitLock;
import org.terracotta.toolkit.concurrent.locks.ToolkitReadWriteLock;

import com.terracotta.entity.internal.InternalRootEntity;
import com.terracotta.entity.internal.LockingEntity;
import com.terracotta.entity.internal.ToolkitAwareEntity;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;

/**
 * ClusteredEntityManager
 */
public class ClusteredEntityManager {

  private static final long TRY_LOCK_TIMEOUT_SECONDS = 2;

  private final Toolkit       toolkit;
  private final EntityLockHandler entityLockHandler;

  private volatile transient ConcurrentMap> entityMapsMap = new ConcurrentHashMap>();

  public ClusteredEntityManager(Toolkit toolkit) {
    this(toolkit, new EntityLockHandler(toolkit));
  }

  ClusteredEntityManager(Toolkit toolkit, EntityLockHandler entityLockHandler) {
    this.toolkit = toolkit;
    this.entityLockHandler = entityLockHandler;
  }

  public  T getRootEntity(String name, Class entityClass) {
    T entity = getRootEntityInternal(name, entityClass);
    if (entity != null && ClusteredEntityState.DESTROY_IN_PROGRESS.equals(entity.getState())) {
      destroyRootEntitySilently(name, entityClass, entity);
      return null;
    }
    return entity;
  }

  public  Map getRootEntities(Class entityClass) {
    HashMap resultMap = new HashMap();
    for (Map.Entry entry : getEntityMap(entityClass).entrySet()) {
      T entity = entry.getValue();
      if (!ClusteredEntityState.DESTROY_IN_PROGRESS.equals(entity.getState())) {
        resultMap.put(entry.getKey(), processEntity(entity));
      } else {
        destroyRootEntitySilently(entry.getKey(), entityClass, entity);
      }
    }
    return Collections.unmodifiableMap(resultMap);
  }

  /**
   * Method for adding a {@link com.terracotta.entity.RootEntity} to this ClusteredEntityManager.
   * 

* If a {@link com.terracotta.entity.RootEntity} of the same clusteredEntityClass with the same name is already known * to this ClusteredEntityManager, that entity will be returned and the clusteredEntity passed in will not added. * * @param name the name of the entity * @param clusteredEntityClass the type of the entity * @param clusteredEntity the clustered entity * * @return the current known mapping if any, {@code null} otherwise */ public T addRootEntityIfAbsent(String name, Class clusteredEntityClass, T clusteredEntity) { ToolkitMap map = getEntityMap(clusteredEntityClass); T oldValue = map.putIfAbsent(name, clusteredEntity); if (oldValue != null) { return processEntity(oldValue); } else { processEntity(clusteredEntity); return null; } } /** * Method for destroying a root entity *

* This method will follow these steps: *

    *
  1. Put entity in exclusive maintenance mode
  2. * If this fails, throws {@link java.lang.IllegalStateException} *
  3. Verify the entity passed in matches the current known entity
  4. * If this fails, throws {@link java.lang.IllegalArgumentException} *
  5. Mark the entity with {@link com.terracotta.entity.ClusteredEntityState#DESTROY_IN_PROGRESS} and save it
  6. * If this fails, throws {@link java.lang.UnsupportedOperationException} *
  7. Perform the destroy operation
  8. *
* * @param name name of the entity to destroy * @param rootEntityClass public interface under which this entity is managed * @param controlEntity the entity to destroy * @param The managed entity type * @return {@code true} if entity was effectively destroyed, {@code false} if entity does not exist */ public boolean destroyRootEntity(String name, Class rootEntityClass, T controlEntity) { InternalRootEntity currentRootEntity = asInternalRootEntity(getRootEntityInternal(name, rootEntityClass)); if (currentRootEntity != null) { ToolkitLock entityWriteLock = currentRootEntity.getEntityLock().writeLock(); try { if (entityWriteLock.tryLock(TRY_LOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS)) { try { if (!currentRootEntity.equals(controlEntity)) { throw new IllegalArgumentException(String.format("The specified entity named %s does not match " + "the mapping known to this entity manager", name)); } currentRootEntity.markDestroying(); try { getEntityMap(rootEntityClass).put(name, (T) currentRootEntity); } catch (Exception e) { // Failed to save entity in destroy state - abort currentRootEntity.alive(); throw new UnsupportedOperationException(String.format("Unable to mark entity %s of type %s with destroy in progress", name, rootEntityClass), e); } currentRootEntity.destroy(); getEntityMap(rootEntityClass).remove(name); return true; } finally { entityWriteLock.unlock(); } } else { throw new IllegalStateException(String.format("Unable to lock entity %s of type %s for destruction", name, rootEntityClass)); } } catch (InterruptedException e) { throw new IllegalStateException(String.format("Unable to lock entity %s of type %s for destruction", name, rootEntityClass), e); } } return false; } private InternalRootEntity asInternalRootEntity(T currentRootEntity) { return (InternalRootEntity) currentRootEntity; } public ToolkitReadWriteLock getEntityLock(String lockName) { return toolkit.getReadWriteLock(lockName); } public void dispose() { entityLockHandler.dispose(); } private T getRootEntityInternal(String name, Class rootEntityClass) { return processEntity(getEntityMap(rootEntityClass).get(name)); } private void destroyRootEntitySilently(String name, Class entityClass, T entity) { try { destroyRootEntity(name, entityClass, entity); } catch (Exception e) { // Ignore - trying to destroy left overs } } private T processEntity(T entity) { if (entity instanceof ToolkitAwareEntity) { ((ToolkitAwareEntity)entity).setToolkit(toolkit); } if (entity instanceof LockingEntity) { ((LockingEntity)entity).setEntityLockHandler(entityLockHandler); } return entity; } private ToolkitMap getEntityMap(Class entityClass) { ToolkitMap entityMap = (ToolkitMap) entityMapsMap.get(entityClass); if (entityMap == null) { entityMap = toolkit.getMap(getMapName(entityClass), String.class, entityClass); ToolkitMap installedMap = (ToolkitMap) entityMapsMap.putIfAbsent(entityClass, entityMap); if (installedMap != null) { entityMap = installedMap; } } return entityMap; } String getMapName(Class entityClass) { return entityClass.getName(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy