public DistributedStateManager( DatabaseCluster<Z, D> cluster, CommandDispatcherFactory dispatcherFactory) throws Exception { this.cluster = cluster; this.stateManager = cluster.getStateManager(); StateCommandContext<Z, D> context = this; this.dispatcher = dispatcherFactory.createCommandDispatcher(cluster.getId() + ".state", context, this, this); }
/** * {@inheritDoc} * * @see net.sf.hajdbc.state.StateManagerFactory#createStateManager(net.sf.hajdbc.DatabaseCluster) */ @Override public <Z, D extends Database<Z>> StateManager createStateManager(DatabaseCluster<Z, D> cluster) { if (this.urlPattern == null) { throw new IllegalArgumentException( "No embedded database driver was detected on the classpath."); } String url = MessageFormat.format(this.urlPattern, cluster.getId(), Strings.HA_JDBC_HOME); DriverDatabase database = new DriverDatabase(); database.setLocation(url); database.setUser(this.user); database.setPassword(this.password); this.logger.log( Level.INFO, "State for database cluster {0} will be persisted to {1}", cluster, url); return new SQLStateManager<Z, D>(cluster, database, new GenericObjectPoolFactory(this)); }
/** * @see net.sf.hajdbc.invocation.InvocationStrategy#invoke(net.sf.hajdbc.sql.SQLProxy, * net.sf.hajdbc.invocation.Invoker) */ @Override public <Z, D extends Database<Z>, T, R, E extends Exception> SortedMap<D, R> invoke( SQLProxy<Z, D, T, E> proxy, Invoker<Z, D, T, R, E> invoker) throws E { Map.Entry<SortedMap<D, R>, SortedMap<D, E>> results = this.collectResults(proxy, invoker); SortedMap<D, R> resultMap = results.getKey(); SortedMap<D, E> exceptionMap = results.getValue(); if (!exceptionMap.isEmpty()) { ExceptionFactory<E> exceptionFactory = proxy.getExceptionFactory(); DatabaseCluster<Z, D> cluster = proxy.getDatabaseCluster(); Dialect dialect = cluster.getDialect(); List<D> failedDatabases = new ArrayList<D>(exceptionMap.size()); // Determine which exceptions are due to failures for (Map.Entry<D, E> entry : exceptionMap.entrySet()) { if (exceptionFactory.indicatesFailure(entry.getValue(), dialect)) { failedDatabases.add(entry.getKey()); } } StateManager stateManager = cluster.getStateManager(); // Deactivate failed databases, unless all failed if (!resultMap.isEmpty() || (failedDatabases.size() < exceptionMap.size())) { for (D failedDatabase : failedDatabases) { E exception = exceptionMap.remove(failedDatabase); if (cluster.deactivate(failedDatabase, stateManager)) { logger.error( "" + exception + "" + Messages.DATABASE_DEACTIVATED.getMessage(), failedDatabase, cluster); } } } if (!exceptionMap.isEmpty()) { // If primary database threw exception if (resultMap.isEmpty() || !exceptionMap.headMap(resultMap.firstKey()).isEmpty()) { D primaryDatabase = exceptionMap.firstKey(); E primaryException = exceptionMap.get(primaryDatabase); // Deactivate databases with non-matching exceptions for (Map.Entry<D, E> entry : exceptionMap.tailMap(primaryDatabase).entrySet()) { E exception = entry.getValue(); if (!exceptionFactory.equals(exception, primaryException)) { D database = entry.getKey(); if (cluster.deactivate(database, stateManager)) { logger.error("" + exception + " " + Messages.DATABASE_INCONSISTENT.getMessage()); } } } // Deactivate databases with results for (Map.Entry<D, R> entry : resultMap.entrySet()) { D database = entry.getKey(); if (cluster.deactivate(database, stateManager)) { logger.error(Messages.DATABASE_INCONSISTENT.getMessage()); } } throw primaryException; } } // Else primary was successful // Deactivate databases with exceptions for (Map.Entry<D, E> entry : exceptionMap.entrySet()) { D database = entry.getKey(); E exception = entry.getValue(); if (cluster.deactivate(database, stateManager)) { logger.error(Messages.DATABASE_DEACTIVATED.getMessage(), database, cluster); } } } return resultMap; }