Java tutorial
/* * Copyright 2014 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.usergrid.corepersistence; import com.google.common.base.Optional; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.util.concurrent.UncheckedExecutionException; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.TypeLiteral; import org.apache.commons.lang.StringUtils; import org.apache.usergrid.corepersistence.asyncevents.AsyncEventService; import org.apache.usergrid.corepersistence.index.CollectionSettingsFactory; import org.apache.usergrid.corepersistence.index.ReIndexRequestBuilder; import org.apache.usergrid.corepersistence.index.ReIndexService; import org.apache.usergrid.corepersistence.service.CollectionService; import org.apache.usergrid.corepersistence.service.ConnectionService; import org.apache.usergrid.corepersistence.util.CpNamingUtils; import org.apache.usergrid.exception.ConflictException; import org.apache.usergrid.locking.LockManager; import org.apache.usergrid.mq.QueueManagerFactory; import org.apache.usergrid.persistence.*; import org.apache.usergrid.persistence.actorsystem.ActorSystemFig; import org.apache.usergrid.persistence.actorsystem.ActorSystemManager; import org.apache.usergrid.persistence.cassandra.CassandraService; import org.apache.usergrid.persistence.cassandra.CounterUtils; import org.apache.usergrid.persistence.cassandra.Setup; import org.apache.usergrid.persistence.collection.EntityCollectionManager; import org.apache.usergrid.persistence.collection.exception.CollectionRuntimeException; import org.apache.usergrid.persistence.collection.serialization.impl.migration.EntityIdScope; import org.apache.usergrid.persistence.collection.uniquevalues.UniqueValuesService; import org.apache.usergrid.persistence.core.metrics.MetricsFactory; import org.apache.usergrid.persistence.core.migration.data.MigrationDataProvider; import org.apache.usergrid.persistence.core.scope.ApplicationScope; import org.apache.usergrid.persistence.core.scope.ApplicationScopeImpl; import org.apache.usergrid.persistence.core.util.Health; import org.apache.usergrid.persistence.entities.Application; import org.apache.usergrid.persistence.exceptions.ApplicationAlreadyExistsException; import org.apache.usergrid.persistence.exceptions.DuplicateUniquePropertyExistsException; import org.apache.usergrid.persistence.exceptions.EntityNotFoundException; import org.apache.usergrid.persistence.graph.*; import org.apache.usergrid.persistence.graph.impl.SimpleSearchByEdgeType; import org.apache.usergrid.persistence.index.EntityIndex; import org.apache.usergrid.persistence.model.entity.Id; import org.apache.usergrid.persistence.model.entity.SimpleId; import org.apache.usergrid.persistence.model.util.UUIDGenerator; import org.apache.usergrid.utils.UUIDUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import rx.Observable; import java.util.*; import static java.lang.String.CASE_INSENSITIVE_ORDER; import static org.apache.usergrid.persistence.Schema.PROPERTY_NAME; import static org.apache.usergrid.persistence.Schema.TYPE_APPLICATION; /** * Implement good-old Usergrid EntityManagerFactory with the new-fangled Core Persistence API. * This is where we keep track of applications and system properties. */ public class CpEntityManagerFactory implements EntityManagerFactory, ApplicationContextAware { private static final Logger logger = LoggerFactory.getLogger(CpEntityManagerFactory.class); private final EntityManagerFig entityManagerFig; private final ActorSystemFig actorSystemFig; private ApplicationContext applicationContext; private Setup setup = null; EntityManager managementAppEntityManager = null; // cache of already instantiated entity managers private final String ENTITY_MANAGER_CACHE_SIZE = "entity.manager.cache.size"; private final LoadingCache<UUID, EntityManager> entityManagers; private final ApplicationIdCache applicationIdCache; Application managementApp = null; private ManagerCache managerCache; private CassandraService cassandraService; private CounterUtils counterUtils; private Injector injector; private final ReIndexService reIndexService; private final MetricsFactory metricsFactory; private final AsyncEventService indexService; private final CollectionService collectionService; private final ConnectionService connectionService; private final GraphManagerFactory graphManagerFactory; private final CollectionSettingsFactory collectionSettingsFactory; private ActorSystemManager actorSystemManager; private UniqueValuesService uniqueValuesService; private final LockManager lockManager; private final QueueManagerFactory queueManagerFactory; public static final String MANAGEMENT_APP_INIT_MAXRETRIES = "management.app.init.max-retries"; public static final String MANAGEMENT_APP_INIT_INTERVAL = "management.app.init.interval"; public CpEntityManagerFactory(final CassandraService cassandraService, final CounterUtils counterUtils, final Injector injector) { this.cassandraService = cassandraService; this.counterUtils = counterUtils; this.injector = injector; this.reIndexService = injector.getInstance(ReIndexService.class); this.entityManagerFig = injector.getInstance(EntityManagerFig.class); this.actorSystemFig = injector.getInstance(ActorSystemFig.class); this.managerCache = injector.getInstance(ManagerCache.class); this.metricsFactory = injector.getInstance(MetricsFactory.class); this.indexService = injector.getInstance(AsyncEventService.class); this.graphManagerFactory = injector.getInstance(GraphManagerFactory.class); this.collectionService = injector.getInstance(CollectionService.class); this.connectionService = injector.getInstance(ConnectionService.class); this.collectionSettingsFactory = injector.getInstance(CollectionSettingsFactory.class); Properties properties = cassandraService.getProperties(); this.entityManagers = createEntityManagerCache(properties); logger.info("EntityManagerFactoring starting..."); if (actorSystemFig.getEnabled()) { try { logger.info("Akka cluster starting..."); this.uniqueValuesService = injector.getInstance(UniqueValuesService.class); this.actorSystemManager = injector.getInstance(ActorSystemManager.class); actorSystemManager.registerRouterProducer(uniqueValuesService); actorSystemManager.start(); actorSystemManager.waitForClientActor(); } catch (Throwable t) { logger.error("Error starting Akka", t); throw t; } } this.lockManager = injector.getInstance(LockManager.class); this.queueManagerFactory = injector.getInstance(QueueManagerFactory.class); // this line always needs to be last due to the temporary cicular dependency until spring is removed this.applicationIdCache = injector.getInstance(ApplicationIdCacheFactory.class) .getInstance(getManagementEntityManager()); checkManagementApp(properties); } private LoadingCache<UUID, EntityManager> createEntityManagerCache(Properties properties) { int entityManagerCacheSize = 100; try { entityManagerCacheSize = Integer.parseInt(properties.getProperty(ENTITY_MANAGER_CACHE_SIZE, "100")); } catch (Exception e) { logger.error("Error parsing " + ENTITY_MANAGER_CACHE_SIZE + ". Will use " + entityManagerCacheSize, e); } return CacheBuilder.newBuilder().maximumSize(entityManagerCacheSize) .build(new CacheLoader<UUID, EntityManager>() { public EntityManager load(UUID appId) { // no checked exception // create new entity manager and pre-fetch its application EntityManager entityManager = _getEntityManager(appId); Application app = null; Throwable throwable = null; try { app = entityManager.getApplication(); } catch (Throwable t) { throwable = t; } // the management app is a special case if (CpNamingUtils.MANAGEMENT_APPLICATION_ID.equals(appId)) { if (app != null) { // we successfully fetched up the management app, cache it for a rainy day managementAppEntityManager = entityManager; } else if (managementAppEntityManager != null) { // failed to fetch management app, use cached one entityManager = managementAppEntityManager; logger.error("Failed to fetch management app"); } } // missing keyspace means we have not done bootstrap yet final boolean isBootstrapping; if (throwable instanceof CollectionRuntimeException) { CollectionRuntimeException cre = (CollectionRuntimeException) throwable; isBootstrapping = cre.isBootstrapping(); } else { isBootstrapping = false; } // work around for https://issues.apache.org/jira/browse/USERGRID-1291 // throw exception so that we do not cache // TODO: determine how application name can intermittently be null if (app != null && app.getName() == null) { throw new RuntimeException("Name is null for application " + appId, throwable); } if (app == null && !isBootstrapping) { throw new RuntimeException("Error getting application " + appId, throwable); } // else keyspace is missing because setup/bootstrap not done yet return entityManager; } }); } private void checkManagementApp(Properties properties) { int maxRetries = 100; try { maxRetries = Integer.parseInt(properties.getProperty(MANAGEMENT_APP_INIT_MAXRETRIES, "100")); } catch (Exception e) { logger.error("Error parsing " + MANAGEMENT_APP_INIT_MAXRETRIES + ". Will use " + maxRetries, e); } int interval = 1000; try { interval = Integer.parseInt(properties.getProperty(MANAGEMENT_APP_INIT_INTERVAL, "1000")); } catch (Exception e) { logger.error("Error parsing " + MANAGEMENT_APP_INIT_INTERVAL + ". Will use " + maxRetries, e); } // hold up construction until we can access the management app int retries = 0; boolean managementAppFound = false; boolean bootstrapping = false; Set<Class> seenBefore = new HashSet<>(10); while (!managementAppFound && retries++ < maxRetries) { try { // bypass entity manager cache and get managementApp managementApp = _getEntityManager(getManagementAppId()).getApplication(); managementAppFound = true; } catch (Throwable t) { if (t instanceof CollectionRuntimeException) { CollectionRuntimeException cre = (CollectionRuntimeException) t; if (cre.isBootstrapping()) { // we're bootstrapping, ignore this and continue bootstrapping = true; break; } } Throwable cause = t; // there was an error, be as informative as possible StringBuilder sb = new StringBuilder(); sb.append(retries).append(": Error ("); if (t instanceof UncheckedExecutionException) { UncheckedExecutionException uee = (UncheckedExecutionException) t; if (uee.getCause() instanceof RuntimeException) { cause = uee.getCause().getCause(); sb.append(cause.getClass().getSimpleName()).append(") ") .append(uee.getCause().getMessage()); } else { cause = uee.getCause(); sb.append(cause.getClass().getSimpleName()).append(") ").append(t.getMessage()); } } else { sb.append(t.getCause().getClass().getSimpleName()).append(") ").append(t.getMessage()); } String msg = sb.toString(); if (!seenBefore.contains(cause.getClass())) { logger.error(msg, t); } else { logger.error(msg); } seenBefore.add(cause.getClass()); try { Thread.sleep(interval); } catch (InterruptedException ignored) { } } } if (!managementAppFound && !bootstrapping) { // exception here will prevent WAR from being deployed throw new RuntimeException("Unable to get management app after " + retries + " retries"); } } public CounterUtils getCounterUtils() { return counterUtils; } public CassandraService getCassandraService() { return cassandraService; } private void initMgmtAppInternal() { EntityManager em = getEntityManager(getManagementAppId()); indexService.queueInitializeApplicationIndex(CpNamingUtils.getApplicationScope(getManagementAppId())); try { if (em.getApplication() == null) { logger.info("Creating management application"); Map mgmtAppProps = new HashMap<String, Object>(); mgmtAppProps.put(PROPERTY_NAME, CassandraService.MANAGEMENT_APPLICATION); em.create(getManagementAppId(), TYPE_APPLICATION, mgmtAppProps); em.getApplication(); } } catch (Exception ex) { throw new RuntimeException("Fatal error creating management application", ex); } } private Observable<EntityIdScope> getAllEntitiesObservable() { return injector.getInstance(Key.get(new TypeLiteral<MigrationDataProvider<EntityIdScope>>() { })).getData(); } @Override public EntityManager getEntityManager(UUID applicationId) { try { return entityManagers.get(applicationId); } catch (Throwable t) { logger.error("Error getting entity manager", t); } return _getEntityManager(applicationId); } private EntityManager _getEntityManager(UUID applicationId) { EntityManager em = new CpEntityManager(cassandraService, counterUtils, indexService, managerCache, metricsFactory, actorSystemFig, entityManagerFig, graphManagerFactory, collectionService, connectionService, collectionSettingsFactory, applicationId, queueManagerFactory); return em; } @Override public Entity createApplicationV2(String organizationName, String name) throws Exception { return createApplicationV2(organizationName, name, null, null, false); } @Override public Entity createApplicationV2(String orgName, String name, UUID applicationId, Map<String, Object> properties, boolean forMigration) throws Exception { String appName = buildAppName(orgName, name); final UUID appId = applicationIdCache.getApplicationId(appName); if (appId != null) { throw new ApplicationAlreadyExistsException(name); } applicationId = applicationId == null ? UUIDGenerator.newTimeUUID() : applicationId; if (logger.isDebugEnabled()) { logger.debug("New application orgName {} orgAppName {} id {} ", orgName, name, applicationId.toString()); } return initializeApplicationV2(orgName, applicationId, appName, properties, forMigration); } private String buildAppName(String organizationName, String name) { return StringUtils.lowerCase(name.contains("/") ? name : organizationName + "/" + name); } /** * @return UUID of newly created Entity of type application_info */ @Override public Entity initializeApplicationV2(String organizationName, final UUID applicationId, String name, Map<String, Object> properties, boolean forMigration) throws Exception { // Ensure the management application is initialized initMgmtAppInternal(); // Get entity managers by bypassing the entity manager cache because it expects apps to already exist final EntityManager managementEm = _getEntityManager(getManagementAppId()); EntityManager appEm = _getEntityManager(applicationId); final String appName = buildAppName(organizationName, name); // check for pre-existing application if (lookupApplication(appName) != null) { throw new ApplicationAlreadyExistsException(appName); } // Initialize the index for this new application appEm.initializeIndex(); indexService.queueInitializeApplicationIndex(CpNamingUtils.getApplicationScope(applicationId)); if (properties == null) { properties = new TreeMap<>(CASE_INSENSITIVE_ORDER); } properties.put(PROPERTY_NAME, appName); appEm.create(applicationId, TYPE_APPLICATION, properties); // only reset roles if this application isn't being migrated (meaning dictionary and role data already exists) if (!forMigration) { appEm.resetRoles(); } // create application info entity in the management app Map<String, Object> appInfoMap = new HashMap<String, Object>() { { put(PROPERTY_NAME, appName); put("org", organizationName); } }; Entity appInfo; try { appInfo = managementEm.create(new SimpleId(applicationId, CpNamingUtils.APPLICATION_INFO), appInfoMap); } catch (DuplicateUniquePropertyExistsException e) { throw new ApplicationAlreadyExistsException(appName); } // evict app Id from cache applicationIdCache.evictAppId(appName); logger.info("Initialized application {}", appName); return appInfo; } /** * Delete Application. * * <p>The Application Entity is be moved to a Deleted_Applications collection and the * Application index will be removed. * * <p>TODO: add scheduled task that can completely delete all deleted application data.</p> * * @param applicationId UUID of Application to be deleted. */ @Override public void deleteApplication(UUID applicationId) throws Exception { // find application_info for application to delete migrateAppInfo(applicationId, CpNamingUtils.APPLICATION_INFO, CpNamingUtils.DELETED_APPLICATION_INFOS, CpNamingUtils.DELETED_APPLICATION_INFO).toBlocking().lastOrDefault(null); } //TODO: return status for restore @Override public Entity restoreApplication(UUID applicationId) throws Exception { // get the deleted_application_info for the deleted app return (Entity) migrateAppInfo(applicationId, CpNamingUtils.DELETED_APPLICATION_INFO, CpNamingUtils.APPLICATION_INFOS, CpNamingUtils.APPLICATION_INFO).lastOrDefault(null) .map(appInfo -> { //start the index rebuild final ReIndexRequestBuilder builder = reIndexService.getBuilder() .withApplicationId(applicationId); reIndexService.rebuildIndex(builder); //load the entity final EntityManager managementEm = getEntityManager(getManagementAppId()); try { return managementEm .get(new SimpleEntityRef(CpNamingUtils.APPLICATION_INFO, applicationId)); } catch (Exception e) { logger.error("Failed to get entity", e); throw new RuntimeException(e); } }).toBlocking().lastOrDefault(null); } // @Override /** * Migrate the application from one type to another. Used in delete and restore * @param applicationUUID The applicationUUID * @param deleteTypeName The type to use on the delete * @param createCollectionName The name of the collection to write the entity into * @param createTypeName The type to use on the create * @return * @throws Exception */ private Observable migrateAppInfo(final UUID applicationUUID, final String deleteTypeName, final String createCollectionName, final String createTypeName) throws Exception { final ApplicationScope managementAppScope = CpNamingUtils .getApplicationScope(CpNamingUtils.MANAGEMENT_APPLICATION_ID); final EntityManager managementEm = getEntityManager(CpNamingUtils.MANAGEMENT_APPLICATION_ID); //the application id we will be removing final Id deleteApplicationId = new SimpleId(applicationUUID, deleteTypeName); //the application id we'll be creating final Id createApplicationId = new SimpleId(applicationUUID, createTypeName); //the application scope of the deleted app to clean it's index final ApplicationScope deleteApplicationScope = new ApplicationScopeImpl(deleteApplicationId); Entity oldAppEntity = managementEm.get(new SimpleEntityRef(deleteTypeName, applicationUUID)); if (oldAppEntity == null) { throw new EntityNotFoundException( String.format("Could not find application with UUID '%s'", applicationUUID)); } // ensure that there is not already a deleted app with the same name final EntityRef alias = managementEm.getAlias(createCollectionName, oldAppEntity.getName()); if (alias != null) { throw new ConflictException("Cannot delete app with same name as already deleted app"); } // make a copy of the app to delete application_info entity // and put it in a deleted_application_info collection final Entity newAppEntity = managementEm.create(new SimpleId(applicationUUID, createTypeName), oldAppEntity.getProperties()); // copy its connections too final Set<String> connectionTypes = managementEm.getConnectionTypes(oldAppEntity); Observable copyConnections = Observable.from(connectionTypes).doOnNext(connType -> { try { final Results connResults = managementEm.getTargetEntities(oldAppEntity, connType, null, Query.Level.ALL_PROPERTIES); connResults.getEntities().forEach(entity -> { try { managementEm.createConnection(newAppEntity, connType, entity); } catch (Exception e) { throw new RuntimeException(e); } }); } catch (Exception e) { throw new RuntimeException(e); } }); final Id managementAppId = CpNamingUtils.getManagementApplicationId(); final EntityIndex aei = getManagementIndex(); final GraphManager managementGraphManager = managerCache.getGraphManager(managementAppScope); final Edge createEdge = CpNamingUtils.createCollectionEdge(managementAppId, createCollectionName, createApplicationId); final Observable createNodeGraph = managementGraphManager.writeEdge(createEdge); final Observable deleteAppFromIndex = aei.deleteApplication(); return Observable.merge(copyConnections, createNodeGraph, deleteAppFromIndex).doOnCompleted(() -> { try { if (oldAppEntity != null) { managementEm.delete(oldAppEntity); applicationIdCache.evictAppId(oldAppEntity.getName()); } EntityIndex ei = getManagementIndex(); ei.refreshAsync().toBlocking().last(); } catch (Exception e) { throw new RuntimeException(e); } }); } @Override public UUID importApplication(String organization, UUID applicationId, String name, Map<String, Object> properties) throws Exception { throw new UnsupportedOperationException("Not supported yet."); } public UUID lookupApplication(String orgAppName) throws Exception { return applicationIdCache.getApplicationId(orgAppName); } @Override public Map<String, UUID> getApplications() throws Exception { return getApplications(CpNamingUtils.getEdgeTypeFromCollectionName(CpNamingUtils.APPLICATION_INFOS)); } @Override public Map<String, UUID> getDeletedApplications() throws Exception { return getApplications( CpNamingUtils.getEdgeTypeFromCollectionName(CpNamingUtils.DELETED_APPLICATION_INFOS)); } private Map<String, UUID> getApplications(final String edgeType) throws Exception { ApplicationScope appScope = CpNamingUtils.getApplicationScope(CpNamingUtils.MANAGEMENT_APPLICATION_ID); GraphManager gm = managerCache.getGraphManager(appScope); EntityManager managementEM = getEntityManager(CpNamingUtils.MANAGEMENT_APPLICATION_ID); Application managementApp = managementEM.getApplication(); if (managementApp == null) { throw new RuntimeException( "Management App " + CpNamingUtils.MANAGEMENT_APPLICATION_ID + " should never be null"); } Id managementId = new SimpleId(managementApp.getUuid(), managementApp.getType()); if (logger.isDebugEnabled()) { logger.debug("getApplications(): Loading edges of edgeType {} from {}:{}", edgeType, managementId.getType(), managementId.getUuid()); } Observable<MarkedEdge> edges = gm.loadEdgesFromSource(new SimpleSearchByEdgeType(managementId, edgeType, Long.MAX_VALUE, SearchByEdgeType.Order.DESCENDING, Optional.<Edge>absent())); final EntityCollectionManager ecm = managerCache.getEntityCollectionManager(appScope); //buffer our edges and batch fetch the app infos for faster I/O return edges.map(edge -> { return edge.getTargetNode(); }).buffer(100).flatMap(entityIds -> { return ecm.load(entityIds); }).flatMap(entitySet -> Observable.from(entitySet.getEntities())) //collect all the app infos into a single map for return .collect(() -> new HashMap<String, UUID>(), (appMap, entity) -> { if (!entity.getEntity().isPresent()) { return; } final org.apache.usergrid.persistence.model.entity.Entity entityData = entity.getEntity().get(); final UUID applicationId = entity.getId().getUuid(); final String applicationName = (String) entityData.getField(PROPERTY_NAME).getValue(); appMap.put(applicationName, applicationId); }).toBlocking().last(); } @Override public void setup() throws Exception { getSetup().initSchema(); lockManager.setup(); } @Override public void bootstrap() throws Exception { // Always make sure the database schema is initialized getSetup().initSchema(); // Roll the new 2.x Migration classes to the latest version supported getSetup().runDataMigration(); // Make sure the management application is created initMgmtAppInternal(); // Ensure management app is initialized getSetup().initMgmtApp(); } @Override public Map<String, String> getServiceProperties() { Map<String, String> props = new HashMap<String, String>(); EntityManager em = getEntityManager(getManagementAppId()); Query q = Query.fromQL("select *"); Results results = null; try { results = em.searchCollection(em.getApplicationRef(), "propertymaps", q); } catch (Exception ex) { logger.error("Error getting system properties", ex); } if (results == null || results.isEmpty()) { return props; } org.apache.usergrid.persistence.Entity e = results.getEntity(); for (String key : e.getProperties().keySet()) { props.put(key, props.get(key).toString()); } return props; } @Override public boolean updateServiceProperties(Map<String, String> properties) { EntityManager em = getEntityManager(getManagementAppId()); Query q = Query.fromQL("select *"); Results results = null; try { results = em.searchCollection(em.getApplicationRef(), "propertymaps", q); } catch (Exception ex) { logger.error("Error getting system properties", ex); return false; } org.apache.usergrid.persistence.Entity propsEntity = null; if (!results.isEmpty()) { propsEntity = results.getEntity(); } else { propsEntity = EntityFactory.newEntity(UUIDUtils.newTimeUUID(), "propertymap"); } // intentionally going only one-level deep into fields and treating all // values as strings because that is all we need for service properties for (String key : properties.keySet()) { propsEntity.setProperty(key, properties.get(key).toString()); } try { em.update(propsEntity); } catch (Exception ex) { logger.error("Error updating service properties", ex); return false; } return true; } @Override public boolean setServiceProperty(final String name, final String value) { return updateServiceProperties(new HashMap<String, String>() { { put(name, value); } }); } @Override public boolean deleteServiceProperty(String name) { EntityManager em = getEntityManager(getManagementAppId()); Query q = Query.fromQL("select *"); Results results = null; try { results = em.searchCollection(em.getApplicationRef(), "propertymaps", q); } catch (Exception ex) { logger.error("Error getting service property for delete of property: {}", name, ex); return false; } org.apache.usergrid.persistence.Entity propsEntity = null; if (!results.isEmpty()) { propsEntity = results.getEntity(); } else { propsEntity = EntityFactory.newEntity(UUIDUtils.newTimeUUID(), "propertymap"); } try { ((AbstractEntity) propsEntity).clearDataset(name); em.update(propsEntity); } catch (Exception ex) { logger.error("Error deleting service property orgAppName: {}", name, ex); return false; } return true; } public ApplicationContext getApplicationContext() { return applicationContext; } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; // try { // setup(); // } catch (Exception ex) { // logger.error("Error setting up EMF", ex); // } } @Override public long performEntityCount() { //TODO, this really needs to be a task that writes this data somewhere since this will get //progressively slower as the system expands return (Long) getAllEntitiesObservable().countLong().toBlocking().last(); } @Override public UUID getManagementAppId() { return CpNamingUtils.MANAGEMENT_APPLICATION_ID; } @Override public EntityManager getManagementEntityManager() { return getEntityManager(CpNamingUtils.MANAGEMENT_APPLICATION_ID); } /** * Gets the setup. * @return Setup helper */ public Setup getSetup() { if (setup == null) { setup = new CpSetup(this, cassandraService, injector); } return setup; } /** * TODO, these 3 methods are super janky. During refactoring we should clean this model up */ public EntityIndex.IndexRefreshCommandInfo refreshIndex(UUID applicationId) { return getEntityManager(applicationId).refreshIndex(); } private EntityIndex getManagementIndex() { return managerCache.getEntityIndex( // management app CpNamingUtils.getApplicationScope(getManagementAppId())); } @Override public void flushEntityManagerCaches() { managerCache.invalidate(); applicationIdCache.evictAll(); Map<UUID, EntityManager> entityManagersMap = entityManagers.asMap(); for (UUID appUuid : entityManagersMap.keySet()) { EntityManager em = entityManagersMap.get(appUuid); em.flushManagerCaches(); } } @Override public Health getEntityStoreHealth() { // could use any collection scope here, does not matter EntityCollectionManager ecm = managerCache.getEntityCollectionManager( new ApplicationScopeImpl(new SimpleId(CpNamingUtils.MANAGEMENT_APPLICATION_ID, "application"))); return ecm.getHealth(); } @Override public Health getIndexHealth() { return getManagementIndex().getIndexHealth(); } @Override public void initializeManagementIndex() { getManagementIndex().initialize(); } }