Hibernate SVN: r12845 - in trunk/HibernateExt/search/src/java/org/hibernate/search: backend/impl/lucene and 3 other directories.
by hibernate-commits@lists.jboss.org
Author: epbernard
Date: 2007-07-29 11:10:49 -0400 (Sun, 29 Jul 2007)
New Revision: 12845
Modified:
trunk/HibernateExt/search/src/java/org/hibernate/search/backend/Workspace.java
trunk/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneBackendQueueProcessor.java
trunk/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneWorker.java
trunk/HibernateExt/search/src/java/org/hibernate/search/engine/SearchFactoryImplementor.java
trunk/HibernateExt/search/src/java/org/hibernate/search/query/FullTextQueryImpl.java
trunk/HibernateExt/search/src/java/org/hibernate/search/store/DirectoryProviderFactory.java
trunk/HibernateExt/search/src/java/org/hibernate/search/store/DirectoryProviderShardingStrategy.java
trunk/HibernateExt/search/src/java/org/hibernate/search/store/IdHashShardingStrategy.java
trunk/HibernateExt/search/src/java/org/hibernate/search/store/NotShardedStrategy.java
Log:
HSEARCH-86 introduce Index Sharding, including sharding strategy
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/backend/Workspace.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/backend/Workspace.java 2007-07-29 14:56:47 UTC (rev 12844)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/backend/Workspace.java 2007-07-29 15:10:49 UTC (rev 12845)
@@ -2,43 +2,39 @@
package org.hibernate.search.backend;
import java.io.IOException;
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.Map;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
-import java.util.Set;
-import java.util.HashSet;
+import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.SimpleAnalyzer;
-import org.apache.lucene.document.Document;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexWriter;
+import org.hibernate.annotations.common.AssertionFailure;
+import org.hibernate.search.SearchException;
import org.hibernate.search.engine.DocumentBuilder;
import org.hibernate.search.engine.SearchFactoryImplementor;
-import org.hibernate.search.SearchException;
import org.hibernate.search.store.DirectoryProvider;
import org.hibernate.search.store.optimization.OptimizerStrategy;
-import org.hibernate.annotations.common.AssertionFailure;
/**
* Lucene workspace.
- * <p>
+ * <p/>
* <b>This is not intended to be used in a multithreaded environment</b>.
* <p/>
* <ul>
- * <li>One cannot execute modification through an IndexReader when an IndexWriter has been acquired
- * on the same underlying directory
+ * <li>One cannot execute modification through an IndexReader when an IndexWriter has been acquired
+ * on the same underlying directory
* </li>
- * <li>One cannot get an IndexWriter when an IndexReader have been acquired and modificed on the same
- * underlying directory
+ * <li>One cannot get an IndexWriter when an IndexReader have been acquired and modificed on the same
+ * underlying directory
* </li>
* <li>The recommended approach is to execute all the modifications on the IndexReaders, {@link #clean()}, and acquire the
- * index writers
+ * index writers
* </li>
* </ul>
*
@@ -53,13 +49,13 @@
private List<DirectoryProvider> lockedProviders = new ArrayList<DirectoryProvider>();
private Map<DirectoryProvider, DPStatistics> dpStatistics = new HashMap<DirectoryProvider, DPStatistics>();
private SearchFactoryImplementor searchFactoryImplementor;
-
+
/**
* Flag indicating if the current work should be executed the Lucene parameters for batch indexing.
*/
private boolean isBatch = false;
-
+
public Workspace(SearchFactoryImplementor searchFactoryImplementor) {
this.searchFactoryImplementor = searchFactoryImplementor;
}
@@ -75,11 +71,11 @@
public IndexReader getIndexReader(DirectoryProvider provider, Class entity) {
//one cannot access a reader for update after a writer has been accessed
if ( writers.containsKey( provider ) )
- throw new AssertionFailure("Tries to read for update an index while a writer is accessed" + entity);
+ throw new AssertionFailure( "Tries to read for update an index while a writer is accessed" + entity );
IndexReader reader = readers.get( provider );
if ( reader != null ) return reader;
lockProvider( provider );
- dpStatistics.get(provider).operations++;
+ dpStatistics.get( provider ).operations++;
try {
reader = IndexReader.open( provider.getDirectory() );
readers.put( provider, reader );
@@ -114,32 +110,30 @@
IndexWriter writer = writers.get( provider );
if ( writer != null ) return writer;
lockProvider( provider );
- if (modificationOperation) dpStatistics.get(provider).operations++;
+ if ( modificationOperation ) dpStatistics.get( provider ).operations++;
try {
Analyzer analyzer = entity != null ?
searchFactoryImplementor.getDocumentBuilders().get( entity ).getAnalyzer() :
new SimpleAnalyzer(); //never used
writer = new IndexWriter( provider.getDirectory(), analyzer, false ); //has been created at init time
- LuceneIndexingParameters indexingParams = searchFactoryImplementor.getIndexingParameters(provider);
- if(isBatch)
- {
- writer.setMergeFactor(indexingParams.getBatchMergeFactor());
- writer.setMaxMergeDocs(indexingParams.getBatchMaxMergeDocs());
- writer.setMaxBufferedDocs(indexingParams.getBatchMaxBufferedDocs());
- }
- else
- {
- writer.setMergeFactor(indexingParams.getMergeFactor());
- writer.setMaxMergeDocs(indexingParams.getMaxMergeDocs());
- writer.setMaxBufferedDocs(indexingParams.getMaxBufferedDocs());
+ LuceneIndexingParameters indexingParams = searchFactoryImplementor.getIndexingParameters( provider );
+ if ( isBatch ) {
+ writer.setMergeFactor( indexingParams.getBatchMergeFactor() );
+ writer.setMaxMergeDocs( indexingParams.getBatchMaxMergeDocs() );
+ writer.setMaxBufferedDocs( indexingParams.getBatchMaxBufferedDocs() );
}
-
+ else {
+ writer.setMergeFactor( indexingParams.getMergeFactor() );
+ writer.setMaxMergeDocs( indexingParams.getMaxMergeDocs() );
+ writer.setMaxBufferedDocs( indexingParams.getMaxBufferedDocs() );
+ }
+
writers.put( provider, writer );
}
catch (IOException e) {
cleanUp(
- new SearchException( "Unable to open IndexWriter" + ( entity != null ? " for " + entity : "" ), e )
+ new SearchException( "Unable to open IndexWriter" + ( entity != null ? " for " + entity : "" ), e )
);
}
return writer;
@@ -159,7 +153,7 @@
private void cleanUp(SearchException originalException) {
//release all readers and writers, then release locks
SearchException raisedException = originalException;
- for ( IndexReader reader : readers.values() ) {
+ for (IndexReader reader : readers.values()) {
try {
reader.close();
}
@@ -175,16 +169,16 @@
readers.clear();
//TODO release lock of all indexes that do not need optimization early
//don't optimze if there is a failure
- if (raisedException == null) {
- for ( DirectoryProvider provider : lockedProviders ) {
- Workspace.DPStatistics stats = dpStatistics.get(provider);
- if (!stats.optimizationForced) {
+ if ( raisedException == null ) {
+ for (DirectoryProvider provider : lockedProviders) {
+ Workspace.DPStatistics stats = dpStatistics.get( provider );
+ if ( !stats.optimizationForced ) {
OptimizerStrategy optimizerStrategy = searchFactoryImplementor.getOptimizerStrategy( provider );
optimizerStrategy.addTransaction( stats.operations );
try {
optimizerStrategy.optimize( this );
}
- catch( SearchException e ) {
+ catch (SearchException e) {
raisedException = new SearchException( "Exception while optimizing directoryProvider: "
+ provider.getDirectory().toString(), e );
break; //no point in continuing
@@ -192,7 +186,7 @@
}
}
}
- for ( IndexWriter writer : writers.values() ) {
+ for (IndexWriter writer : writers.values()) {
try {
writer.close();
}
@@ -205,7 +199,7 @@
}
}
}
- for ( DirectoryProvider provider : lockedProviders ) {
+ for (DirectoryProvider provider : lockedProviders) {
searchFactoryImplementor.getLockableDirectoryProviders().get( provider ).unlock();
}
writers.clear();
@@ -221,18 +215,9 @@
cleanUp( null );
}
- public void optimize(Class entity) {
- DocumentBuilder documentBuilders = searchFactoryImplementor.getDocumentBuilders().get( entity );
- DirectoryProvider[] providers = documentBuilders.getDirectoryProviderSelectionStrategy()
- .getDirectoryProvidersForOptimization( entity );
- for (DirectoryProvider provider: providers) {
- optimize( provider );
- }
- }
-
- private void optimize(DirectoryProvider provider) {
+ public void optimize(DirectoryProvider provider) {
OptimizerStrategy optimizerStrategy = searchFactoryImplementor.getOptimizerStrategy( provider );
- dpStatistics.get(provider).optimizationForced = true;
+ dpStatistics.get( provider ).optimizationForced = true;
optimizerStrategy.optimizationForced();
}
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneBackendQueueProcessor.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneBackendQueueProcessor.java 2007-07-29 14:56:47 UTC (rev 12844)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneBackendQueueProcessor.java 2007-07-29 15:10:49 UTC (rev 12845)
@@ -71,9 +71,7 @@
}
}
else if ( OptimizeLuceneWork.class.isAssignableFrom( work.getClass() ) ) {
- DirectoryProvider[] providers = shardingStrategy.getDirectoryProvidersForOptimization(
- work.getEntityClass()
- );
+ DirectoryProvider[] providers = shardingStrategy.getDirectoryProvidersForAllShards();
for (DirectoryProvider provider : providers) {
queueWithFlatDPs.add( new LuceneWorker.WorkWithPayload(work, provider) );
}
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneWorker.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneWorker.java 2007-07-29 14:56:47 UTC (rev 12844)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneWorker.java 2007-07-29 15:10:49 UTC (rev 12845)
@@ -13,13 +13,13 @@
import org.apache.lucene.index.TermDocs;
import org.hibernate.annotations.common.AssertionFailure;
import org.hibernate.search.SearchException;
-import org.hibernate.search.store.DirectoryProvider;
import org.hibernate.search.backend.AddLuceneWork;
import org.hibernate.search.backend.DeleteLuceneWork;
import org.hibernate.search.backend.LuceneWork;
+import org.hibernate.search.backend.OptimizeLuceneWork;
import org.hibernate.search.backend.Workspace;
-import org.hibernate.search.backend.OptimizeLuceneWork;
import org.hibernate.search.engine.DocumentBuilder;
+import org.hibernate.search.store.DirectoryProvider;
/**
* Stateless implementation that performs a unit of work.
@@ -105,11 +105,11 @@
throw new SearchException( "Unable to remove from Lucene index: " + entity + "#" + id, e );
}
finally {
- if (termDocs != null) try {
+ if ( termDocs != null ) try {
termDocs.close();
}
catch (IOException e) {
- log.warn( "Unable to close termDocs properly", e);
+ log.warn( "Unable to close termDocs properly", e );
}
}
@@ -122,7 +122,7 @@
IndexWriter writer = workspace.getIndexWriter( provider, entity, false );
try {
writer.optimize();
- workspace.optimize(entity);
+ workspace.optimize( provider );
}
catch (IOException e) {
throw new SearchException( "Unable to optimize Lucene index: " + entity, e );
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/engine/SearchFactoryImplementor.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/engine/SearchFactoryImplementor.java 2007-07-29 14:56:47 UTC (rev 12844)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/engine/SearchFactoryImplementor.java 2007-07-29 15:10:49 UTC (rev 12845)
@@ -5,16 +5,16 @@
import java.util.concurrent.locks.ReentrantLock;
import org.hibernate.search.SearchFactory;
+import org.hibernate.search.backend.BackendQueueProcessorFactory;
+import org.hibernate.search.backend.LuceneIndexingParameters;
+import org.hibernate.search.backend.Worker;
import org.hibernate.search.filter.FilterCachingStrategy;
import org.hibernate.search.store.DirectoryProvider;
import org.hibernate.search.store.optimization.OptimizerStrategy;
-import org.hibernate.search.backend.BackendQueueProcessorFactory;
-import org.hibernate.search.backend.LuceneIndexingParameters;
-import org.hibernate.search.backend.Worker;
/**
* Interface which gives access to the different directory providers and their configuration.
- *
+ *
* @author Emmanuel Bernard
* @author Hardy Ferentschik
*/
@@ -36,8 +36,8 @@
FilterCachingStrategy getFilterCachingStrategy();
FilterDef getFilterDefinition(String name);
-
- public LuceneIndexingParameters getIndexingParameters(DirectoryProvider<?> provider );
-
+
+ public LuceneIndexingParameters getIndexingParameters(DirectoryProvider<?> provider);
+
void addIndexingParmeters(DirectoryProvider<?> provider, LuceneIndexingParameters indexingParams);
}
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/query/FullTextQueryImpl.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/query/FullTextQueryImpl.java 2007-07-29 14:56:47 UTC (rev 12844)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/query/FullTextQueryImpl.java 2007-07-29 15:10:49 UTC (rev 12845)
@@ -408,7 +408,7 @@
//no class means all classes
for (DocumentBuilder builder : builders.values()) {
final DirectoryProvider[] directoryProviders =
- builder.getDirectoryProviderSelectionStrategy().getDirectoryProvidersForQuery();
+ builder.getDirectoryProviderSelectionStrategy().getDirectoryProvidersForAllShards();
for (DirectoryProvider provider : directoryProviders) {
if ( !directories.contains( provider ) ) {
directories.add( provider );
@@ -430,7 +430,7 @@
if ( builder == null )
throw new HibernateException( "Not a mapped entity (don't forget to add @Indexed): " + clazz );
final DirectoryProvider[] directoryProviders =
- builder.getDirectoryProviderSelectionStrategy().getDirectoryProvidersForQuery();
+ builder.getDirectoryProviderSelectionStrategy().getDirectoryProvidersForAllShards();
for (DirectoryProvider provider : directoryProviders) {
if ( !directories.contains( provider ) ) {
directories.add( provider );
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/store/DirectoryProviderFactory.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/store/DirectoryProviderFactory.java 2007-07-29 14:56:47 UTC (rev 12844)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/store/DirectoryProviderFactory.java 2007-07-29 15:10:49 UTC (rev 12845)
@@ -71,7 +71,10 @@
int nbrOfProviders = indexProps.length;
DirectoryProvider[] providers = new DirectoryProvider[nbrOfProviders];
for (int index = 0 ; index < nbrOfProviders ; index++) {
- providers[index] = createDirectoryProvider(directoryProviderName + "_" + index,indexProps[index], searchFactoryImplementor);
+ String providerName = nbrOfProviders > 1 ?
+ directoryProviderName + "_" + index :
+ directoryProviderName;
+ providers[index] = createDirectoryProvider( providerName,indexProps[index], searchFactoryImplementor);
}
//define sharding strategy
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/store/DirectoryProviderShardingStrategy.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/store/DirectoryProviderShardingStrategy.java 2007-07-29 14:56:47 UTC (rev 12844)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/store/DirectoryProviderShardingStrategy.java 2007-07-29 15:10:49 UTC (rev 12845)
@@ -11,8 +11,7 @@
*/
public interface DirectoryProviderShardingStrategy {
void init(Properties properties, DirectoryProvider[] providers);
- DirectoryProvider[] getDirectoryProvidersForQuery();
+ DirectoryProvider[] getDirectoryProvidersForAllShards();
DirectoryProvider getDirectoryProviderForAddition(Class entity, Serializable id, String idInString, Document document);
DirectoryProvider[] getDirectoryProvidersForDeletion(Class entity, Serializable id, String idInString);
- DirectoryProvider[] getDirectoryProvidersForOptimization(Class entity);
}
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/store/IdHashShardingStrategy.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/store/IdHashShardingStrategy.java 2007-07-29 14:56:47 UTC (rev 12844)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/store/IdHashShardingStrategy.java 2007-07-29 15:10:49 UTC (rev 12845)
@@ -17,7 +17,7 @@
this.providers = providers;
}
- public DirectoryProvider[] getDirectoryProvidersForQuery() {
+ public DirectoryProvider[] getDirectoryProvidersForAllShards() {
return providers;
}
@@ -29,10 +29,6 @@
return new DirectoryProvider[] { providers[ hashKey(idInString) ] };
}
- public DirectoryProvider[] getDirectoryProvidersForOptimization(Class entity) {
- return providers;
- }
-
private int hashKey(String key) {
//reproduce the hashCode implementaiton of String as documented in the javadoc
// to be safe cross Java version (in case it changes some day)
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/store/NotShardedStrategy.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/store/NotShardedStrategy.java 2007-07-29 14:56:47 UTC (rev 12844)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/store/NotShardedStrategy.java 2007-07-29 15:10:49 UTC (rev 12845)
@@ -19,7 +19,7 @@
}
}
- public DirectoryProvider[] getDirectoryProvidersForQuery() {
+ public DirectoryProvider[] getDirectoryProvidersForAllShards() {
return directoryProvider;
}
@@ -31,7 +31,4 @@
return directoryProvider;
}
- public DirectoryProvider[] getDirectoryProvidersForOptimization(Class entity) {
- return directoryProvider;
- }
}
17 years, 5 months
Hibernate SVN: r12844 - in trunk/HibernateExt/search/src: java/org/hibernate/search/backend and 8 other directories.
by hibernate-commits@lists.jboss.org
Author: epbernard
Date: 2007-07-29 10:56:47 -0400 (Sun, 29 Jul 2007)
New Revision: 12844
Added:
trunk/HibernateExt/search/src/java/org/hibernate/search/store/DirectoryProviderShardingStrategy.java
trunk/HibernateExt/search/src/java/org/hibernate/search/store/IdHashShardingStrategy.java
trunk/HibernateExt/search/src/java/org/hibernate/search/store/NotShardedStrategy.java
trunk/HibernateExt/search/src/test/org/hibernate/search/test/shards/
trunk/HibernateExt/search/src/test/org/hibernate/search/test/shards/Animal.java
trunk/HibernateExt/search/src/test/org/hibernate/search/test/shards/ShardsTest.java
Modified:
trunk/HibernateExt/search/src/java/org/hibernate/search/SearchFactory.java
trunk/HibernateExt/search/src/java/org/hibernate/search/backend/AddLuceneWork.java
trunk/HibernateExt/search/src/java/org/hibernate/search/backend/DeleteLuceneWork.java
trunk/HibernateExt/search/src/java/org/hibernate/search/backend/LuceneWork.java
trunk/HibernateExt/search/src/java/org/hibernate/search/backend/OptimizeLuceneWork.java
trunk/HibernateExt/search/src/java/org/hibernate/search/backend/Workspace.java
trunk/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneBackendQueueProcessor.java
trunk/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneWorker.java
trunk/HibernateExt/search/src/java/org/hibernate/search/engine/DocumentBuilder.java
trunk/HibernateExt/search/src/java/org/hibernate/search/impl/SearchFactoryImpl.java
trunk/HibernateExt/search/src/java/org/hibernate/search/query/FullTextQueryImpl.java
trunk/HibernateExt/search/src/java/org/hibernate/search/store/DirectoryProviderFactory.java
trunk/HibernateExt/search/src/test/org/hibernate/search/test/SearchTestCase.java
trunk/HibernateExt/search/src/test/org/hibernate/search/test/jms/master/JMSMasterTest.java
Log:
HSEARCH-86 introduce Index Sharding, including sharding strategy
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/SearchFactory.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/SearchFactory.java 2007-07-29 14:12:13 UTC (rev 12843)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/SearchFactory.java 2007-07-29 14:56:47 UTC (rev 12844)
@@ -19,7 +19,7 @@
* Provide access to the DirectoryProvider (hence the Lucene Directory)
* for a given entity
*/
- DirectoryProvider getDirectoryProvider(Class entity);
+ DirectoryProvider[] getDirectoryProviders(Class entity);
/**
* Optimize all indexes
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/backend/AddLuceneWork.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/backend/AddLuceneWork.java 2007-07-29 14:12:13 UTC (rev 12843)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/backend/AddLuceneWork.java 2007-07-29 14:56:47 UTC (rev 12844)
@@ -9,7 +9,7 @@
* @author Emmanuel Bernard
*/
public class AddLuceneWork extends LuceneWork {
- public AddLuceneWork(Serializable id, Class entity, Document document) {
- super( id, entity, document );
+ public AddLuceneWork(Serializable id, String idInString, Class entity, Document document) {
+ super( id, idInString, entity, document );
}
}
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/backend/DeleteLuceneWork.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/backend/DeleteLuceneWork.java 2007-07-29 14:12:13 UTC (rev 12843)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/backend/DeleteLuceneWork.java 2007-07-29 14:56:47 UTC (rev 12844)
@@ -7,7 +7,7 @@
* @author Emmanuel Bernard
*/
public class DeleteLuceneWork extends LuceneWork {
- public DeleteLuceneWork(Serializable id, Class entity) {
- super( id, entity );
+ public DeleteLuceneWork(Serializable id, String idInString, Class entity) {
+ super( id, idInString, entity );
}
}
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/backend/LuceneWork.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/backend/LuceneWork.java 2007-07-29 14:12:13 UTC (rev 12843)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/backend/LuceneWork.java 2007-07-29 14:56:47 UTC (rev 12844)
@@ -21,13 +21,15 @@
* Flag indicating if this lucene work has to be indexed in batch mode.
*/
private boolean batch = false;
+ private String idInString;
- public LuceneWork(Serializable id, Class entity) {
- this( id, entity, null );
+ public LuceneWork(Serializable id, String idInString, Class entity) {
+ this( id, idInString, entity, null );
}
- public LuceneWork(Serializable id, Class entity, Document document) {
+ public LuceneWork(Serializable id, String idInString, Class entity, Document document) {
this.id = id;
+ this.idInString = idInString;
this.entityClass = entity;
this.document = document;
}
@@ -51,4 +53,8 @@
public Serializable getId() {
return id;
}
+
+ public String getIdInString() {
+ return idInString;
+ }
}
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/backend/OptimizeLuceneWork.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/backend/OptimizeLuceneWork.java 2007-07-29 14:12:13 UTC (rev 12843)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/backend/OptimizeLuceneWork.java 2007-07-29 14:56:47 UTC (rev 12844)
@@ -9,6 +9,6 @@
*/
public class OptimizeLuceneWork extends LuceneWork {
public OptimizeLuceneWork(Class entity) {
- super( null, entity );
+ super( null, null, entity );
}
}
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/backend/Workspace.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/backend/Workspace.java 2007-07-29 14:12:13 UTC (rev 12843)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/backend/Workspace.java 2007-07-29 14:56:47 UTC (rev 12844)
@@ -2,10 +2,13 @@
package org.hibernate.search.backend;
import java.io.IOException;
+import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
+import java.util.HashSet;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.commons.logging.Log;
@@ -14,6 +17,7 @@
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.SimpleAnalyzer;
+import org.apache.lucene.document.Document;
import org.hibernate.search.engine.DocumentBuilder;
import org.hibernate.search.engine.SearchFactoryImplementor;
import org.hibernate.search.SearchException;
@@ -65,18 +69,13 @@
}
/**
- * Retrieve an IndexWriter for a given entity
- *
- * @param entity entity processed
- * @param modificationOperation true if the modification is expected to be an idnex state change
- * @return appropriate indexWriter
+ * retrieve a read write IndexReader
+ * For a given DirectoryProvider, An IndexReader must be used before an IndexWriter
*/
- public IndexReader getIndexReader(Class entity, boolean modificationOperation) {
- //TODO NPEs
- DirectoryProvider provider = searchFactoryImplementor.getDirectoryProvider( entity );
+ public IndexReader getIndexReader(DirectoryProvider provider, Class entity) {
//one cannot access a reader for update after a writer has been accessed
if ( writers.containsKey( provider ) )
- throw new AssertionFailure("Tries to read for update a index while a writer is accessed" + entity);
+ throw new AssertionFailure("Tries to read for update an index while a writer is accessed" + entity);
IndexReader reader = readers.get( provider );
if ( reader != null ) return reader;
lockProvider( provider );
@@ -91,24 +90,16 @@
return reader;
}
- /**
- * Retrieve an IndexWriter for a given entity
- *
- * @param entity entity processed
- * @param modificationOperation true if the modification is expected to be an idnex state change
- * @return appropriate indexWriter
- */
- public IndexWriter getIndexWriter(Class entity, boolean modificationOperation) {
- DirectoryProvider provider = searchFactoryImplementor.getDirectoryProvider( entity );
- return getIndexWriter( provider, entity, modificationOperation );
- }
-
//for optimization
public IndexWriter getIndexWriter(DirectoryProvider provider) {
return getIndexWriter( provider, null, false );
}
- private IndexWriter getIndexWriter(DirectoryProvider provider, Class entity, boolean modificationOperation) {
+ /**
+ * retrieve a read write IndexWriter
+ * For a given DirectoryProvider, An IndexReader must be used before an IndexWriter
+ */
+ public IndexWriter getIndexWriter(DirectoryProvider provider, Class entity, boolean modificationOperation) {
//one has to close a reader for update before a writer is accessed
IndexReader reader = readers.get( provider );
if ( reader != null ) {
@@ -123,7 +114,7 @@
IndexWriter writer = writers.get( provider );
if ( writer != null ) return writer;
lockProvider( provider );
- dpStatistics.get(provider).operations++;
+ if (modificationOperation) dpStatistics.get(provider).operations++;
try {
Analyzer analyzer = entity != null ?
searchFactoryImplementor.getDocumentBuilders().get( entity ).getAnalyzer() :
@@ -231,7 +222,15 @@
}
public void optimize(Class entity) {
- DirectoryProvider provider = searchFactoryImplementor.getDirectoryProvider( entity );
+ DocumentBuilder documentBuilders = searchFactoryImplementor.getDocumentBuilders().get( entity );
+ DirectoryProvider[] providers = documentBuilders.getDirectoryProviderSelectionStrategy()
+ .getDirectoryProvidersForOptimization( entity );
+ for (DirectoryProvider provider: providers) {
+ optimize( provider );
+ }
+ }
+
+ private void optimize(DirectoryProvider provider) {
OptimizerStrategy optimizerStrategy = searchFactoryImplementor.getOptimizerStrategy( provider );
dpStatistics.get(provider).optimizationForced = true;
optimizerStrategy.optimizationForced();
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneBackendQueueProcessor.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneBackendQueueProcessor.java 2007-07-29 14:12:13 UTC (rev 12843)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneBackendQueueProcessor.java 2007-07-29 14:56:47 UTC (rev 12844)
@@ -4,6 +4,7 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
+import java.util.ArrayList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -11,8 +12,12 @@
import org.hibernate.search.backend.LuceneWork;
import org.hibernate.search.backend.Workspace;
import org.hibernate.search.backend.OptimizeLuceneWork;
+import org.hibernate.search.backend.DeleteLuceneWork;
import org.hibernate.search.engine.SearchFactoryImplementor;
+import org.hibernate.search.engine.DocumentBuilder;
import org.hibernate.search.store.DirectoryProvider;
+import org.hibernate.search.store.DirectoryProviderShardingStrategy;
+import org.hibernate.annotations.common.AssertionFailure;
/**
* Apply the operations to Lucene directories avoiding deadlocks.
@@ -41,9 +46,45 @@
workspace = new Workspace( searchFactoryImplementor );
worker = new LuceneWorker( workspace );
try {
- deadlockFreeQueue(queue, workspace, searchFactoryImplementor);
+ List<LuceneWorker.WorkWithPayload> queueWithFlatDPs = new ArrayList<LuceneWorker.WorkWithPayload>( queue.size()*2 );
+ for ( LuceneWork work : queue ) {
+ DocumentBuilder documentBuilder = searchFactoryImplementor.getDocumentBuilders().get( work.getEntityClass() );
+ DirectoryProviderShardingStrategy shardingStrategy = documentBuilder.getDirectoryProviderSelectionStrategy();
+
+ if ( AddLuceneWork.class.isAssignableFrom( work.getClass() ) ) {
+ DirectoryProvider provider = shardingStrategy.getDirectoryProviderForAddition(
+ work.getEntityClass(),
+ work.getId(),
+ work.getIdInString(),
+ work.getDocument()
+ );
+ queueWithFlatDPs.add( new LuceneWorker.WorkWithPayload(work, provider) );
+ }
+ else if ( DeleteLuceneWork.class.isAssignableFrom( work.getClass() ) ) {
+ DirectoryProvider[] providers = shardingStrategy.getDirectoryProvidersForDeletion(
+ work.getEntityClass(),
+ work.getId(),
+ work.getIdInString()
+ );
+ for (DirectoryProvider provider : providers) {
+ queueWithFlatDPs.add( new LuceneWorker.WorkWithPayload(work, provider) );
+ }
+ }
+ else if ( OptimizeLuceneWork.class.isAssignableFrom( work.getClass() ) ) {
+ DirectoryProvider[] providers = shardingStrategy.getDirectoryProvidersForOptimization(
+ work.getEntityClass()
+ );
+ for (DirectoryProvider provider : providers) {
+ queueWithFlatDPs.add( new LuceneWorker.WorkWithPayload(work, provider) );
+ }
+ }
+ else {
+ throw new AssertionFailure( "Unknown work type: " + work.getClass() );
+ }
+ }
+ deadlockFreeQueue(queueWithFlatDPs, searchFactoryImplementor);
checkForBatchIndexing(workspace);
- for ( LuceneWork luceneWork : queue ) {
+ for ( LuceneWorker.WorkWithPayload luceneWork : queueWithFlatDPs ) {
worker.performWork( luceneWork );
}
}
@@ -57,8 +98,9 @@
for ( LuceneWork luceneWork : queue ) {
// if there is at least a single batch index job we put the work space into batch indexing mode.
if(luceneWork.isBatch()){
- log.debug("Setting batch indexing mode.");
+ log.trace("Setting batch indexing mode.");
workspace.setBatch(true);
+ break;
}
}
}
@@ -68,9 +110,9 @@
* dead lock between concurrent threads or processes
* To achieve that, the work will be done per directory provider
*/
- private void deadlockFreeQueue(List<LuceneWork> queue, final Workspace workspace, final SearchFactoryImplementor searchFactoryImplementor) {
- Collections.sort( queue, new Comparator<LuceneWork>() {
- public int compare(LuceneWork o1, LuceneWork o2) {
+ private void deadlockFreeQueue(List<LuceneWorker.WorkWithPayload> queue, final SearchFactoryImplementor searchFactoryImplementor) {
+ Collections.sort( queue, new Comparator<LuceneWorker.WorkWithPayload>() {
+ public int compare(LuceneWorker.WorkWithPayload o1, LuceneWorker.WorkWithPayload o2) {
long h1 = getWorkHashCode( o1, searchFactoryImplementor );
long h2 = getWorkHashCode( o2, searchFactoryImplementor );
return h1 < h2 ?
@@ -82,14 +124,13 @@
} );
}
- private long getWorkHashCode(LuceneWork luceneWork, SearchFactoryImplementor searchFactoryImplementor) {
- Class entity = luceneWork.getEntityClass();
- DirectoryProvider provider = searchFactoryImplementor.getDirectoryProvider( entity );
+ private long getWorkHashCode(LuceneWorker.WorkWithPayload luceneWork, SearchFactoryImplementor searchFactoryImplementor) {
+ DirectoryProvider provider = luceneWork.getProvider();
int h = provider.getClass().hashCode();
h = 31 * h + provider.hashCode();
long extendedHash = h; //to be sure extendedHash + 1 < extendedHash + 2 is always true
- if ( luceneWork instanceof AddLuceneWork ) extendedHash+=1; //addwork after deleteWork
- if ( luceneWork instanceof OptimizeLuceneWork ) extendedHash+=2; //optimize after everything
+ if ( luceneWork.getWork() instanceof AddLuceneWork ) extendedHash+=1; //addwork after deleteWork
+ if ( luceneWork.getWork() instanceof OptimizeLuceneWork ) extendedHash+=2; //optimize after everything
return extendedHash;
}
}
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneWorker.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneWorker.java 2007-07-29 14:12:13 UTC (rev 12843)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/backend/impl/lucene/LuceneWorker.java 2007-07-29 14:56:47 UTC (rev 12844)
@@ -13,6 +13,7 @@
import org.apache.lucene.index.TermDocs;
import org.hibernate.annotations.common.AssertionFailure;
import org.hibernate.search.SearchException;
+import org.hibernate.search.store.DirectoryProvider;
import org.hibernate.search.backend.AddLuceneWork;
import org.hibernate.search.backend.DeleteLuceneWork;
import org.hibernate.search.backend.LuceneWork;
@@ -34,32 +35,33 @@
this.workspace = workspace;
}
- public void performWork(LuceneWork luceneWork) {
- if ( AddLuceneWork.class.isAssignableFrom( luceneWork.getClass() ) ) {
- performWork( (AddLuceneWork) luceneWork );
+ public void performWork(WorkWithPayload luceneWork) {
+ Class workClass = luceneWork.getWork().getClass();
+ if ( AddLuceneWork.class.isAssignableFrom( workClass ) ) {
+ performWork( (AddLuceneWork) luceneWork.getWork(), luceneWork.getProvider() );
}
- else if ( DeleteLuceneWork.class.isAssignableFrom( luceneWork.getClass() ) ) {
- performWork( (DeleteLuceneWork) luceneWork );
+ else if ( DeleteLuceneWork.class.isAssignableFrom( workClass ) ) {
+ performWork( (DeleteLuceneWork) luceneWork.getWork(), luceneWork.getProvider() );
}
- else if ( OptimizeLuceneWork.class.isAssignableFrom( luceneWork.getClass() ) ) {
- performWork( (OptimizeLuceneWork) luceneWork );
+ else if ( OptimizeLuceneWork.class.isAssignableFrom( workClass ) ) {
+ performWork( (OptimizeLuceneWork) luceneWork.getWork(), luceneWork.getProvider() );
}
else {
- throw new AssertionFailure( "Unknown work type: " + luceneWork.getClass() );
+ throw new AssertionFailure( "Unknown work type: " + workClass );
}
}
- public void performWork(AddLuceneWork work) {
+ public void performWork(AddLuceneWork work, DirectoryProvider provider) {
Class entity = work.getEntityClass();
Serializable id = work.getId();
Document document = work.getDocument();
- add( entity, id, document );
+ add( entity, id, document, provider );
}
- private void add(Class entity, Serializable id, Document document) {
+ private void add(Class entity, Serializable id, Document document, DirectoryProvider provider) {
if ( log.isTraceEnabled() )
log.trace( "add to Lucene index: " + entity + "#" + id + ": " + document );
- IndexWriter writer = workspace.getIndexWriter( entity, true );
+ IndexWriter writer = workspace.getIndexWriter( provider, entity, true );
try {
writer.addDocument( document );
}
@@ -68,22 +70,22 @@
}
}
- public void performWork(DeleteLuceneWork work) {
+ public void performWork(DeleteLuceneWork work, DirectoryProvider provider) {
Class entity = work.getEntityClass();
Serializable id = work.getId();
- remove( entity, id );
+ remove( entity, id, provider );
}
- private void remove(Class entity, Serializable id) {
+ private void remove(Class entity, Serializable id, DirectoryProvider provider) {
/**
- * even with Lucene 2.1, use of indexWriter to delte is not an option
+ * even with Lucene 2.1, use of indexWriter to delete is not an option
* We can only delete by term, and the index doesn't have a termt that
* uniquely identify the entry. See logic below
*/
log.trace( "remove from Lucene index: " + entity + "#" + id );
DocumentBuilder builder = workspace.getDocumentBuilder( entity );
Term term = builder.getTerm( id );
- IndexReader reader = workspace.getIndexReader( entity, true );
+ IndexReader reader = workspace.getIndexReader( provider, entity );
TermDocs termDocs = null;
try {
//TODO is there a faster way?
@@ -110,15 +112,14 @@
log.warn( "Unable to close termDocs properly", e);
}
}
+
}
- public void performWork(OptimizeLuceneWork work) {
+ public void performWork(OptimizeLuceneWork work, DirectoryProvider provider) {
Class entity = work.getEntityClass();
if ( log.isTraceEnabled() )
log.trace( "optimize Lucene index: " + entity );
- //TODO get a batchIndexWriter of some kind that deals with different merge factors and all
- //TODO this one should not compete with a regular IndexWriter (ie exception from the workspace)
- IndexWriter writer = workspace.getIndexWriter( entity, false );
+ IndexWriter writer = workspace.getIndexWriter( provider, entity, false );
try {
writer.optimize();
workspace.optimize(entity);
@@ -127,4 +128,24 @@
throw new SearchException( "Unable to optimize Lucene index: " + entity, e );
}
}
+
+ public static class WorkWithPayload {
+ private LuceneWork work;
+ private DirectoryProvider provider;
+
+
+ public WorkWithPayload(LuceneWork work, DirectoryProvider provider) {
+ this.work = work;
+ this.provider = provider;
+ }
+
+
+ public LuceneWork getWork() {
+ return work;
+ }
+
+ public DirectoryProvider getProvider() {
+ return provider;
+ }
+ }
}
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/engine/DocumentBuilder.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/engine/DocumentBuilder.java 2007-07-29 14:12:13 UTC (rev 12843)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/engine/DocumentBuilder.java 2007-07-29 14:56:47 UTC (rev 12844)
@@ -44,6 +44,7 @@
import org.hibernate.search.bridge.FieldBridge;
import org.hibernate.search.bridge.TwoWayFieldBridge;
import org.hibernate.search.store.DirectoryProvider;
+import org.hibernate.search.store.DirectoryProviderShardingStrategy;
import org.hibernate.search.util.BinderHelper;
import org.hibernate.search.util.ScopedAnalyzer;
@@ -61,7 +62,8 @@
private final PropertiesMetadata rootPropertiesMetadata;
private final XClass beanClass;
- private final DirectoryProvider directoryProvider;
+ private final DirectoryProvider[] directoryProviders;
+ private final DirectoryProviderShardingStrategy shardingStrategy;
private String idKeywordName;
private XMember idGetter;
private Float idBoost;
@@ -74,11 +76,12 @@
private ScopedAnalyzer analyzer;
- public DocumentBuilder(XClass clazz, Analyzer defaultAnalyzer, DirectoryProvider directory,
- ReflectionManager reflectionManager) {
+ public DocumentBuilder(XClass clazz, Analyzer defaultAnalyzer, DirectoryProvider[] directoryProviders,
+ DirectoryProviderShardingStrategy shardingStrategy, ReflectionManager reflectionManager) {
this.analyzer = new ScopedAnalyzer();
this.beanClass = clazz;
- this.directoryProvider = directory;
+ this.directoryProviders = directoryProviders;
+ this.shardingStrategy = shardingStrategy;
//FIXME get rid of it when boost is stored?
this.reflectionManager = reflectionManager;
@@ -387,13 +390,14 @@
}
boolean searchForContainers = false;
+ String idInString = idBridge.objectToString( id );
if ( workType == WorkType.ADD ) {
Document doc = getDocument( entity, id );
- queue.add( new AddLuceneWork( id, entityClass, doc ) );
+ queue.add( new AddLuceneWork( id, idInString, entityClass, doc ) );
searchForContainers = true;
}
else if ( workType == WorkType.DELETE ) {
- queue.add( new DeleteLuceneWork( id, entityClass ) );
+ queue.add( new DeleteLuceneWork( id, idInString, entityClass ) );
}
else if ( workType == WorkType.UPDATE ) {
Document doc = getDocument( entity, id );
@@ -404,14 +408,14 @@
* But essentially the optimization we are doing is the same Lucene is doing, the only extra cost is the
* double file opening.
*/
- queue.add( new DeleteLuceneWork( id, entityClass ) );
- queue.add( new AddLuceneWork( id, entityClass, doc ) );
+ queue.add( new DeleteLuceneWork( id, idInString, entityClass ) );
+ queue.add( new AddLuceneWork( id, idInString, entityClass, doc ) );
searchForContainers = true;
}
else if ( workType == WorkType.INDEX ) {
Document doc = getDocument( entity, id );
- queue.add( new DeleteLuceneWork( id, entityClass ) );
- LuceneWork work = new AddLuceneWork( id, entityClass, doc );
+ queue.add( new DeleteLuceneWork( id, idInString, entityClass ) );
+ LuceneWork work = new AddLuceneWork( id, idInString, entityClass, doc );
work.setBatch( true );
queue.add( work );
searchForContainers = true;
@@ -578,10 +582,14 @@
return new Term( idKeywordName, idBridge.objectToString( id ) );
}
- public DirectoryProvider getDirectoryProvider() {
- return directoryProvider;
+ public DirectoryProvider[] getDirectoryProviders() {
+ return directoryProviders;
}
+ public DirectoryProviderShardingStrategy getDirectoryProviderSelectionStrategy() {
+ return shardingStrategy;
+ }
+
public Analyzer getAnalyzer() {
return analyzer;
}
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/impl/SearchFactoryImpl.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/impl/SearchFactoryImpl.java 2007-07-29 14:12:13 UTC (rev 12843)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/impl/SearchFactoryImpl.java 2007-07-29 14:56:47 UTC (rev 12844)
@@ -226,9 +226,9 @@
return reflectionManager;
}
- public DirectoryProvider getDirectoryProvider(Class entity) {
+ public DirectoryProvider[] getDirectoryProviders(Class entity) {
DocumentBuilder<Object> documentBuilder = getDocumentBuilders().get( entity );
- return documentBuilder == null ? null : documentBuilder.getDirectoryProvider();
+ return documentBuilder == null ? null : documentBuilder.getDirectoryProviders();
}
public void optimize() {
@@ -257,13 +257,11 @@
XClass mappedXClass = reflectionManager.toXClass(mappedClass);
if ( mappedXClass != null) {
if ( mappedXClass.isAnnotationPresent( Indexed.class ) ) {
- DirectoryProvider provider = factory.createDirectoryProvider( mappedXClass, cfg, this );
- //TODO move that into DirectoryProviderFactory
- if ( !lockableDirectoryProviders.containsKey( provider ) ) {
- lockableDirectoryProviders.put( provider, new ReentrantLock() );
- }
+ DirectoryProviderFactory.DirectoryProviders providers = factory.createDirectoryProviders( mappedXClass, cfg, this );
+
final DocumentBuilder<Object> documentBuilder = new DocumentBuilder<Object>(
- mappedXClass, analyzer, provider, reflectionManager
+ mappedXClass, analyzer, providers.getProviders(), providers.getSelectionStrategy(),
+ reflectionManager
);
documentBuilders.put( mappedClass, documentBuilder );
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/query/FullTextQueryImpl.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/query/FullTextQueryImpl.java 2007-07-29 14:12:13 UTC (rev 12843)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/query/FullTextQueryImpl.java 2007-07-29 14:56:47 UTC (rev 12844)
@@ -407,9 +407,12 @@
if ( classes == null || classes.length == 0 ) {
//no class means all classes
for (DocumentBuilder builder : builders.values()) {
- final DirectoryProvider directoryProvider = builder.getDirectoryProvider();
- if ( !directories.contains( directoryProvider ) ) {
- directories.add( directoryProvider );
+ final DirectoryProvider[] directoryProviders =
+ builder.getDirectoryProviderSelectionStrategy().getDirectoryProvidersForQuery();
+ for (DirectoryProvider provider : directoryProviders) {
+ if ( !directories.contains( provider ) ) {
+ directories.add( provider );
+ }
}
}
classesAndSubclasses = null;
@@ -426,9 +429,12 @@
//TODO should we rather choose a polymorphic path and allow non mapped entities
if ( builder == null )
throw new HibernateException( "Not a mapped entity (don't forget to add @Indexed): " + clazz );
- final DirectoryProvider directoryProvider = builder.getDirectoryProvider();
- if ( !directories.contains( directoryProvider ) ) {
- directories.add( directoryProvider );
+ final DirectoryProvider[] directoryProviders =
+ builder.getDirectoryProviderSelectionStrategy().getDirectoryProvidersForQuery();
+ for (DirectoryProvider provider : directoryProviders) {
+ if ( !directories.contains( provider ) ) {
+ directories.add( provider );
+ }
}
}
classesAndSubclasses = involvedClasses;
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/store/DirectoryProviderFactory.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/store/DirectoryProviderFactory.java 2007-07-29 14:12:13 UTC (rev 12843)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/store/DirectoryProviderFactory.java 2007-07-29 14:56:47 UTC (rev 12844)
@@ -5,6 +5,8 @@
import java.util.List;
import java.util.Map;
import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.locks.ReentrantLock;
import org.hibernate.HibernateException;
import org.hibernate.cfg.Configuration;
@@ -15,6 +17,7 @@
import org.hibernate.search.store.optimization.OptimizerStrategy;
import org.hibernate.search.store.optimization.IncrementalOptimizerStrategy;
import org.hibernate.search.store.optimization.NoOpOptimizerStrategy;
+import org.hibernate.search.SearchException;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.annotations.common.reflection.XClass;
@@ -47,7 +50,7 @@
private static String LUCENE_DEFAULT = LUCENE_PREFIX + "default.";
private static String DEFAULT_DIRECTORY_PROVIDER = FSDirectoryProvider.class.getName();
- // Lucene index performance paramters
+ // Lucene index performance parameters
private static final String MERGE_FACTOR = "merge_factor";
private static final String MAX_MERGE_DOCS = "max_merge_docs";
private static final String MAX_BUFFERED_DOCS = "max_buffered_docs";
@@ -55,13 +58,66 @@
private static final String BATCH_MAX_MERGE_DOCS = "max_merge_docs.batch";
private static final String BATCH_MAX_BUFFERED_DOCS = "max_buffered_docs.batch";
- //TODO for the public?
- public DirectoryProvider<?> createDirectoryProvider(XClass entity, Configuration cfg, SearchFactoryImplementor searchFactoryImplementor) {
+ private static final String SHARDING_STRATEGY = "sharding_strategy";
+ private static final String NBR_OF_SHARDS = SHARDING_STRATEGY + ".nbr_of_shards";
+
+
+ public DirectoryProviders createDirectoryProviders(XClass entity, Configuration cfg, SearchFactoryImplementor searchFactoryImplementor) {
//get properties
String directoryProviderName = getDirectoryProviderName( entity, cfg );
- Properties indexProps = getDirectoryProperties( cfg, directoryProviderName );
+ Properties[] indexProps = getDirectoryProperties( cfg, directoryProviderName );
- //set up the directory
+ //set up the directories
+ int nbrOfProviders = indexProps.length;
+ DirectoryProvider[] providers = new DirectoryProvider[nbrOfProviders];
+ for (int index = 0 ; index < nbrOfProviders ; index++) {
+ providers[index] = createDirectoryProvider(directoryProviderName + "_" + index,indexProps[index], searchFactoryImplementor);
+ }
+
+ //define sharding strategy
+ DirectoryProviderShardingStrategy shardingStrategy;
+ Properties shardingProperties = new Properties();
+ for (Map.Entry entry : indexProps[0].entrySet()) {
+ if ( ( (String) entry.getKey() ).startsWith( SHARDING_STRATEGY ) ) {
+ shardingProperties.put( entry.getKey(), entry.getValue() );
+ }
+ }
+ String shardingStrategyName = shardingProperties.getProperty( SHARDING_STRATEGY );
+ if ( shardingStrategyName == null) {
+ if ( indexProps.length == 1 ) {
+ shardingStrategy = new NotShardedStrategy();
+ }
+ else {
+ shardingStrategy = new IdHashShardingStrategy();
+ }
+ }
+ else {
+ try {
+ Class shardigStrategyClass = ReflectHelper.classForName( shardingStrategyName, this.getClass() );
+ shardingStrategy = (DirectoryProviderShardingStrategy) shardigStrategyClass.newInstance();
+ }
+ catch (ClassNotFoundException e) {
+ throw new SearchException("Unable to find ShardingStrategy class " + shardingStrategyName + " for " + directoryProviderName, e);
+ }
+ catch (IllegalAccessException e) {
+ throw new SearchException("Unable to create instance of ShardingStrategy class " + shardingStrategyName
+ + " Be sure to have a no-arg constructor", e);
+ }
+ catch (InstantiationException e) {
+ throw new SearchException("Unable to create instance of ShardingStrategy class " + shardingStrategyName
+ + " Be sure to have a no-arg constructor", e);
+ }
+ catch (ClassCastException e) {
+ throw new SearchException("ShardingStrategy class does not implements DirecotryProviderShardingStrategy: "
+ + shardingStrategyName, e);
+ }
+ }
+ shardingStrategy.init( shardingProperties, providers );
+
+ return new DirectoryProviders( shardingStrategy, providers );
+ }
+
+ private DirectoryProvider<?> createDirectoryProvider(String directoryProviderName, Properties indexProps, SearchFactoryImplementor searchFactoryImplementor) {
String className = indexProps.getProperty( "directory_provider" );
if ( StringHelper.isEmpty( className ) ) {
className = DEFAULT_DIRECTORY_PROVIDER;
@@ -92,6 +148,9 @@
configureOptimizerStrategy(searchFactoryImplementor, indexProps, provider);
configureIndexingParameters(searchFactoryImplementor, indexProps, provider);
providers.add( provider );
+ if ( !searchFactoryImplementor.getLockableDirectoryProviders().containsKey( provider ) ) {
+ searchFactoryImplementor.getLockableDirectoryProviders().put( provider, new ReentrantLock() );
+ }
return provider;
}
}
@@ -186,26 +245,96 @@
}
}
searchFactoryImplementor.addIndexingParmeters(provider, indexingParams);
- }
+ }
- private static Properties getDirectoryProperties(Configuration cfg, String directoryProviderName) {
+ /**
+ * Returns an array of directory properties
+ * Properties are defaulted. For a given proeprty name,
+ * hibernate.search.indexname.n has priority over hibernate.search.indexname which has priority over hibernate.search
+ * If the Index is not sharded, a single Properties is returned
+ * If the index is sharded, the Properties index matches the shard index
+ */
+ private static Properties[] getDirectoryProperties(Configuration cfg, String directoryProviderName) {
Properties props = cfg.getProperties();
String indexName = LUCENE_PREFIX + directoryProviderName;
- Properties indexProps = new Properties();
- Properties indexSpecificProps = new Properties();
+ //indexSpecificProperties[i] >> indexSpecificDefaultproperties >> defaultProperties
+ Properties defaultProperties = new Properties();
+ ArrayList<Properties> indexSpecificProps = new ArrayList<Properties>();
+ Properties indexSpecificDefaultProps = new Properties(defaultProperties);
for ( Map.Entry entry : props.entrySet() ) {
String key = (String) entry.getKey();
if ( key.startsWith( LUCENE_DEFAULT ) ) {
- indexProps.setProperty( key.substring( LUCENE_DEFAULT.length() ), (String) entry.getValue() );
+ defaultProperties.setProperty( key.substring( LUCENE_DEFAULT.length() ), (String) entry.getValue() );
}
else if ( key.startsWith( indexName ) ) {
- indexSpecificProps.setProperty( key.substring( indexName.length() ), (String) entry.getValue() );
+ String suffixedKey = key.substring( indexName.length() + 1 );
+ int nextDoc = suffixedKey.indexOf( '.' );
+ int index = -1;
+ if ( nextDoc != -1 ) {
+ String potentialNbr = suffixedKey.substring( 0, nextDoc );
+ try {
+ index = Integer.parseInt( potentialNbr );
+ }
+ catch ( Exception e ) {
+ //just not a number
+ index = -1;
+ }
+ }
+ if (index == -1) {
+ indexSpecificDefaultProps.setProperty( suffixedKey, (String) entry.getValue() );
+ }
+ else {
+ String finalKeyName = suffixedKey.substring( nextDoc + 1 );
+ //ignore sharding strategy properties
+ if ( ! finalKeyName.startsWith( SHARDING_STRATEGY ) ) {
+ ensureListSize( indexSpecificProps, index + 1 );
+ Properties propertiesforIndex = indexSpecificProps.get( index );
+ if ( propertiesforIndex == null ) {
+ propertiesforIndex = new Properties( indexSpecificDefaultProps );
+ indexSpecificProps.set( index, propertiesforIndex );
+ }
+ propertiesforIndex.setProperty( finalKeyName, (String) entry.getValue() );
+ }
+ }
}
}
- indexProps.putAll( indexSpecificProps );
- return indexProps;
+ String nbrOfShardsString = indexSpecificDefaultProps.getProperty( NBR_OF_SHARDS );
+ int nbrOfShards = -1;
+ if ( nbrOfShardsString != null ) {
+ try {
+ nbrOfShards = Integer.parseInt( nbrOfShardsString );
+ }
+ catch (NumberFormatException e) {
+ throw new SearchException(indexName + "." + NBR_OF_SHARDS + " is not a number", e);
+ }
+ }
+ if ( nbrOfShards <= 0 && indexSpecificProps.size() == 0 ) {
+ //no shard (a shareded subindex has to have at least one property
+ return new Properties[] { indexSpecificDefaultProps };
+ }
+ else {
+ //sharded
+ nbrOfShards = nbrOfShards >= indexSpecificDefaultProps.size() ?
+ nbrOfShards :
+ indexSpecificDefaultProps.size();
+ ensureListSize( indexSpecificProps, nbrOfShards );
+ for ( int index = 0 ; index < nbrOfShards ; index++ ) {
+ if ( indexSpecificProps.get( index ) == null ) {
+ indexSpecificProps.set( index, new Properties( indexSpecificDefaultProps ) );
+ }
+ }
+ return indexSpecificProps.toArray( new Properties[ indexSpecificProps.size() ] );
+ }
}
+ private static void ensureListSize(ArrayList<Properties> indexSpecificProps, int size) {
+ //ensure the index exists
+ indexSpecificProps.ensureCapacity( size );
+ while ( indexSpecificProps.size() < size ) {
+ indexSpecificProps.add(null);
+ }
+ }
+
private static String getDirectoryProviderName(XClass clazz, Configuration cfg) {
//yuk
ReflectionManager reflectionManager = SearchFactoryImpl.getReflectionManager(cfg);
@@ -237,4 +366,24 @@
"Trying to extract the index name from a non @Indexed class: " + clazz.getName() );
}
}
+
+ public class DirectoryProviders {
+ private DirectoryProviderShardingStrategy shardingStrategy;
+ private DirectoryProvider[] providers;
+
+
+ public DirectoryProviders(DirectoryProviderShardingStrategy shardingStrategy, DirectoryProvider[] providers) {
+ this.shardingStrategy = shardingStrategy;
+ this.providers = providers;
+ }
+
+
+ public DirectoryProviderShardingStrategy getSelectionStrategy() {
+ return shardingStrategy;
+ }
+
+ public DirectoryProvider[] getProviders() {
+ return providers;
+ }
+ }
}
Added: trunk/HibernateExt/search/src/java/org/hibernate/search/store/DirectoryProviderShardingStrategy.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/store/DirectoryProviderShardingStrategy.java (rev 0)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/store/DirectoryProviderShardingStrategy.java 2007-07-29 14:56:47 UTC (rev 12844)
@@ -0,0 +1,18 @@
+//$Id$
+package org.hibernate.search.store;
+
+import java.io.Serializable;
+import java.util.Properties;
+
+import org.apache.lucene.document.Document;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public interface DirectoryProviderShardingStrategy {
+ void init(Properties properties, DirectoryProvider[] providers);
+ DirectoryProvider[] getDirectoryProvidersForQuery();
+ DirectoryProvider getDirectoryProviderForAddition(Class entity, Serializable id, String idInString, Document document);
+ DirectoryProvider[] getDirectoryProvidersForDeletion(Class entity, Serializable id, String idInString);
+ DirectoryProvider[] getDirectoryProvidersForOptimization(Class entity);
+}
Added: trunk/HibernateExt/search/src/java/org/hibernate/search/store/IdHashShardingStrategy.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/store/IdHashShardingStrategy.java (rev 0)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/store/IdHashShardingStrategy.java 2007-07-29 14:56:47 UTC (rev 12844)
@@ -0,0 +1,46 @@
+//$Id$
+package org.hibernate.search.store;
+
+import java.util.Properties;
+import java.io.Serializable;
+
+import org.apache.lucene.document.Document;
+
+/**
+ * This implementation use idInString as the hashKey.
+ *
+ * @author Emmanuel Bernard
+ */
+public class IdHashShardingStrategy implements DirectoryProviderShardingStrategy {
+ private DirectoryProvider[] providers;
+ public void init(Properties properties, DirectoryProvider[] providers) {
+ this.providers = providers;
+ }
+
+ public DirectoryProvider[] getDirectoryProvidersForQuery() {
+ return providers;
+ }
+
+ public DirectoryProvider getDirectoryProviderForAddition(Class entity, Serializable id, String idInString, Document document) {
+ return providers[ hashKey(idInString) ];
+ }
+
+ public DirectoryProvider[] getDirectoryProvidersForDeletion(Class entity, Serializable id, String idInString) {
+ return new DirectoryProvider[] { providers[ hashKey(idInString) ] };
+ }
+
+ public DirectoryProvider[] getDirectoryProvidersForOptimization(Class entity) {
+ return providers;
+ }
+
+ private int hashKey(String key) {
+ //reproduce the hashCode implementaiton of String as documented in the javadoc
+ // to be safe cross Java version (in case it changes some day)
+ int hash = 0;
+ int length = key.length();
+ for (int index = 0 ; index < length ; index++) {
+ hash = 31*hash + key.charAt( index );
+ }
+ return hash % providers.length;
+ }
+}
Added: trunk/HibernateExt/search/src/java/org/hibernate/search/store/NotShardedStrategy.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/store/NotShardedStrategy.java (rev 0)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/store/NotShardedStrategy.java 2007-07-29 14:56:47 UTC (rev 12844)
@@ -0,0 +1,37 @@
+//$Id$
+package org.hibernate.search.store;
+
+import java.util.Properties;
+import java.io.Serializable;
+
+import org.apache.lucene.document.Document;
+import org.hibernate.annotations.common.AssertionFailure;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class NotShardedStrategy implements DirectoryProviderShardingStrategy {
+ private DirectoryProvider[] directoryProvider;
+ public void init(Properties properties, DirectoryProvider[] providers) {
+ this.directoryProvider = providers;
+ if ( directoryProvider.length > 1) {
+ throw new AssertionFailure("Using SingleDirectoryProviderSelectionStrategy with multiple DirectryProviders");
+ }
+ }
+
+ public DirectoryProvider[] getDirectoryProvidersForQuery() {
+ return directoryProvider;
+ }
+
+ public DirectoryProvider getDirectoryProviderForAddition(Class entity, Serializable id, String idInString, Document document) {
+ return directoryProvider[0];
+ }
+
+ public DirectoryProvider[] getDirectoryProvidersForDeletion(Class entity, Serializable id, String idInString) {
+ return directoryProvider;
+ }
+
+ public DirectoryProvider[] getDirectoryProvidersForOptimization(Class entity) {
+ return directoryProvider;
+ }
+}
Modified: trunk/HibernateExt/search/src/test/org/hibernate/search/test/SearchTestCase.java
===================================================================
--- trunk/HibernateExt/search/src/test/org/hibernate/search/test/SearchTestCase.java 2007-07-29 14:12:13 UTC (rev 12843)
+++ trunk/HibernateExt/search/src/test/org/hibernate/search/test/SearchTestCase.java 2007-07-29 14:56:47 UTC (rev 12844)
@@ -20,7 +20,7 @@
}
protected Directory getDirectory(Class clazz) {
- return getLuceneEventListener().getSearchFactoryImplementor().getDirectoryProvider( clazz ).getDirectory();
+ return getLuceneEventListener().getSearchFactoryImplementor().getDirectoryProviders( clazz )[0].getDirectory();
}
private FullTextIndexEventListener getLuceneEventListener() {
Modified: trunk/HibernateExt/search/src/test/org/hibernate/search/test/jms/master/JMSMasterTest.java
===================================================================
--- trunk/HibernateExt/search/src/test/org/hibernate/search/test/jms/master/JMSMasterTest.java 2007-07-29 14:12:13 UTC (rev 12843)
+++ trunk/HibernateExt/search/src/test/org/hibernate/search/test/jms/master/JMSMasterTest.java 2007-07-29 14:56:47 UTC (rev 12844)
@@ -57,7 +57,7 @@
doc.add( field );
field = new Field("logo", ts.getLogo(), Field.Store.NO, Field.Index.TOKENIZED );
doc.add( field );
- LuceneWork luceneWork = new AddLuceneWork(ts.getId(), ts.getClass(), doc );
+ LuceneWork luceneWork = new AddLuceneWork(ts.getId(), String.valueOf( ts.getId() ), ts.getClass(), doc );
List<LuceneWork> queue = new ArrayList<LuceneWork>();
queue.add( luceneWork );
Added: trunk/HibernateExt/search/src/test/org/hibernate/search/test/shards/Animal.java
===================================================================
--- trunk/HibernateExt/search/src/test/org/hibernate/search/test/shards/Animal.java (rev 0)
+++ trunk/HibernateExt/search/src/test/org/hibernate/search/test/shards/Animal.java 2007-07-29 14:56:47 UTC (rev 12844)
@@ -0,0 +1,40 @@
+//$Id$
+package org.hibernate.search.test.shards;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+import org.hibernate.search.annotations.Indexed;
+import org.hibernate.search.annotations.DocumentId;
+import org.hibernate.search.annotations.Field;
+import org.hibernate.search.annotations.Index;
+
+/**
+ * @author Emmanuel Bernard
+ */
+@Entity
+@Indexed(index = "Animal")
+public class Animal {
+ @Id
+ @DocumentId
+ private Integer id;
+ @Field(index = Index.TOKENIZED)
+ private String name;
+
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
Added: trunk/HibernateExt/search/src/test/org/hibernate/search/test/shards/ShardsTest.java
===================================================================
--- trunk/HibernateExt/search/src/test/org/hibernate/search/test/shards/ShardsTest.java (rev 0)
+++ trunk/HibernateExt/search/src/test/org/hibernate/search/test/shards/ShardsTest.java 2007-07-29 14:56:47 UTC (rev 12844)
@@ -0,0 +1,190 @@
+//$Id$
+package org.hibernate.search.test.shards;
+
+import java.io.File;
+import java.util.Properties;
+import java.util.List;
+
+import org.hibernate.search.test.SearchTestCase;
+import org.hibernate.search.store.RAMDirectoryProvider;
+import org.hibernate.search.store.FSDirectoryProvider;
+import org.hibernate.search.store.IdHashShardingStrategy;
+import org.hibernate.search.store.DirectoryProvider;
+import org.hibernate.search.Environment;
+import org.hibernate.search.FullTextSession;
+import org.hibernate.search.Search;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.apache.lucene.analysis.StopAnalyzer;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.TermDocs;
+import org.apache.lucene.index.Term;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class ShardsTest extends SearchTestCase {
+
+
+ protected void configure(Configuration cfg) {
+ super.configure( cfg );
+ cfg.setProperty( "hibernate.search.default.directory_provider", FSDirectoryProvider.class.getName() );
+ File sub = getBaseIndexDir();
+ cfg.setProperty( "hibernate.search.default.indexBase", sub.getAbsolutePath() );
+ cfg.setProperty( Environment.ANALYZER_CLASS, StopAnalyzer.class.getName() );
+ //is the default when multiple shards are set up
+ //cfg.setProperty( "hibernate.search.Animal.sharding_strategy", IdHashShardingStrategy.class );
+ cfg.setProperty( "hibernate.search.Animal.sharding_strategy.nbr_of_shards", "2" );
+ cfg.setProperty( "hibernate.search.Animal.0.indexName", "Animal00" );
+ }
+
+ public void testIdShardingStrategy() {
+ DirectoryProvider[] dps = new DirectoryProvider[] { new RAMDirectoryProvider(), new RAMDirectoryProvider() };
+ IdHashShardingStrategy shardingStrategy = new IdHashShardingStrategy();
+ shardingStrategy.init( null, dps);
+ assertTrue( dps[1] == shardingStrategy.getDirectoryProviderForAddition( Animal.class, 1, "1", null) );
+ assertTrue( dps[0] == shardingStrategy.getDirectoryProviderForAddition( Animal.class, 2, "2", null) );
+ }
+
+ public void testBehavior() throws Exception {
+ Session s = openSession( );
+ Transaction tx = s.beginTransaction();
+ Animal a = new Animal();
+ a.setId( 1 );
+ a.setName( "Elephant" );
+ s.persist( a );
+ a = new Animal();
+ a.setId( 2 );
+ a.setName( "Bear" );
+ s.persist( a );
+ tx.commit();
+
+ s.clear();
+
+ tx = s.beginTransaction();
+ a = (Animal) s.get(Animal.class, 1);
+ a.setName( "Mouse" );
+ tx.commit();
+
+ s.clear();
+
+ tx = s.beginTransaction();
+ FullTextSession fts = Search.createFullTextSession( s );
+ QueryParser parser = new QueryParser("id", new StopAnalyzer() );
+
+ List results = fts.createFullTextQuery( parser.parse( "name:mouse OR name:bear" ) ).list();
+ assertEquals( "Either double insert, single update, or query fails with shards", 2, results.size() );
+ for (Object o : results) s.delete( o );
+ tx.commit();
+ s.close();
+ }
+
+ public void testInternalSharding() throws Exception {
+ Session s = openSession( );
+ Transaction tx = s.beginTransaction();
+ Animal a = new Animal();
+ a.setId( 1 );
+ a.setName( "Elephant" );
+ s.persist( a );
+ a = new Animal();
+ a.setId( 2 );
+ a.setName( "Bear" );
+ s.persist( a );
+ tx.commit();
+
+ s.clear();
+
+ IndexReader reader = IndexReader.open( new File( getBaseIndexDir(), "Animal00" ) );
+ try {
+ int num = reader.numDocs();
+ assertEquals( 1, num );
+ }
+ finally {
+ reader.close();
+ }
+ reader = IndexReader.open( new File( getBaseIndexDir(), "Animal_1" ) );
+ try {
+ int num = reader.numDocs();
+ assertEquals( 1, num );
+ }
+ finally {
+ reader.close();
+ }
+
+
+ tx = s.beginTransaction();
+ a = (Animal) s.get(Animal.class, 1);
+ a.setName( "Mouse" );
+ tx.commit();
+
+ s.clear();
+
+ reader = IndexReader.open( new File( getBaseIndexDir(), "Animal_1" ) );
+ try {
+ int num = reader.numDocs();
+ assertEquals( 1, num );
+ TermDocs docs = reader.termDocs( new Term( "name", "mouse" ) );
+ assertTrue( docs.next() );
+ org.apache.lucene.document.Document doc = reader.document( docs.doc() );
+ assertFalse( docs.next() );
+ }
+ finally {
+ reader.close();
+ }
+
+ tx = s.beginTransaction();
+ FullTextSession fts = Search.createFullTextSession( s );
+ QueryParser parser = new QueryParser("id", new StopAnalyzer() );
+
+ List results = fts.createFullTextQuery( parser.parse( "name:mouse OR name:bear" ) ).list();
+ assertEquals( "Either double insert, single update, or query fails with shards", 2, results.size() );
+ for (Object o : results) s.delete( o );
+ tx.commit();
+ s.close();
+ }
+
+ protected void setUp() throws Exception {
+ File sub = getBaseIndexDir();
+ sub.mkdir();
+ File[] files = sub.listFiles();
+ for (File file : files) {
+ if ( file.isDirectory() ) {
+ delete( file );
+ }
+ }
+ //super.setUp(); //we need a fresh session factory each time for index set up
+ buildSessionFactory( getMappings(), getAnnotatedPackages(), getXmlFiles() );
+ }
+
+ private File getBaseIndexDir() {
+ File current = new File( "." );
+ File sub = new File( current, "indextemp" );
+ return sub;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ File sub = getBaseIndexDir();
+ delete( sub );
+ }
+
+ private void delete(File sub) {
+ if ( sub.isDirectory() ) {
+ for ( File file : sub.listFiles() ) {
+ delete( file );
+ }
+ sub.delete();
+ }
+ else {
+ sub.delete();
+ }
+ }
+
+ protected Class[] getMappings() {
+ return new Class[] {
+ Animal.class
+ };
+ }
+}
17 years, 5 months
Hibernate SVN: r12843 - trunk/HibernateExt/search/src/java/org/hibernate/search/util.
by hibernate-commits@lists.jboss.org
Author: epbernard
Date: 2007-07-29 10:12:13 -0400 (Sun, 29 Jul 2007)
New Revision: 12843
Modified:
trunk/HibernateExt/search/src/java/org/hibernate/search/util/DirectoryProviderHelper.java
Log:
HSEARCH-103 introduct indexName to override the directoryprovider name
Modified: trunk/HibernateExt/search/src/java/org/hibernate/search/util/DirectoryProviderHelper.java
===================================================================
--- trunk/HibernateExt/search/src/java/org/hibernate/search/util/DirectoryProviderHelper.java 2007-07-28 21:28:06 UTC (rev 12842)
+++ trunk/HibernateExt/search/src/java/org/hibernate/search/util/DirectoryProviderHelper.java 2007-07-29 14:12:13 UTC (rev 12843)
@@ -72,6 +72,7 @@
public static File determineIndexDir(String directoryProviderName, Properties properties) {
String indexBase = properties.getProperty( "indexBase", "." );
+ String indexName = properties.getProperty( "indexName", directoryProviderName );
File indexDir = new File( indexBase );
if ( ! indexDir.exists() ) {
//if the base directory does not exists, create it
@@ -85,7 +86,7 @@
throw new SearchException( "Cannot write into index directory: " + indexBase );
}
- indexDir = new File( indexDir, directoryProviderName );
+ indexDir = new File( indexDir, indexName );
return indexDir;
}
}
17 years, 5 months
Hibernate SVN: r12842 - in shards/trunk: src/test/org/hibernate/shards and 4 other directories.
by hibernate-commits@lists.jboss.org
Author: max.ross
Date: 2007-07-28 17:28:06 -0400 (Sat, 28 Jul 2007)
New Revision: 12842
Added:
shards/trunk/src/test/org/hibernate/shards/example/
shards/trunk/src/test/org/hibernate/shards/example/WeatherReport.java
shards/trunk/src/test/org/hibernate/shards/example/WeatherReportApp.java
shards/trunk/src/test/org/hibernate/shards/example/hibernate0.cfg.xml
shards/trunk/src/test/org/hibernate/shards/example/hibernate1.cfg.xml
shards/trunk/src/test/org/hibernate/shards/example/hibernate2.cfg.xml
shards/trunk/src/test/org/hibernate/shards/example/weather.hbm.xml
shards/trunk/src/test/org/hibernate/shards/util/DatabaseUtils.java
Modified:
shards/trunk/doc/reference/en/modules/configuration.xml
shards/trunk/doc/reference/en/modules/limitations.xml
shards/trunk/src/test/org/hibernate/shards/integration/BaseShardingIntegrationTestCase.java
shards/trunk/src/test/org/hibernate/shards/integration/platform/hsql/HSQLDatabasePlatform.java
Log:
added in a sample app that matches the samples in the documentation
Modified: shards/trunk/doc/reference/en/modules/configuration.xml
===================================================================
--- shards/trunk/doc/reference/en/modules/configuration.xml 2007-07-28 06:39:31 UTC (rev 12841)
+++ shards/trunk/doc/reference/en/modules/configuration.xml 2007-07-28 21:28:06 UTC (rev 12842)
@@ -132,7 +132,7 @@
15
16 ShardStrategyFactory buildShardStrategyFactory() {
17 ShardStrategyFactory shardStrategyFactory = new ShardStrategyFactory() {
-18 public ShardStrategy newShardStrategy(List shardIds) {
+18 public ShardStrategy newShardStrategy(List<ShardId> shardIds) {
19 RoundRobinShardLoadBalancer loadBalancer = new RoundRobinShardLoadBalancer(shardIds);
20 ShardSelectionStrategy pss = new RoundRobinShardSelectionStrategy(loadBalancer);
21 ShardResolutionStrategy prs = new AllShardsShardResolutionStrategy(shardIds);
@@ -223,7 +223,7 @@
3 <session-factory name="HibernateSessionFactory0"> <!-- note the different name -->
4 <property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
5 <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
- 6 <property name="connection.url">jdbc:mysql://localhost:3306/mydb</property>
+ 6 <property name="connection.url">jdbc:mysql://dbhost0:3306/mydb</property>
7 <property name="connection.username">my_user</property>
8 <property name="connection.password">my_password</property>
9 <property name="hibernate.connection.shard_id">0</property> <!-- new -->
@@ -237,7 +237,7 @@
3 <session-factory name="HibernateSessionFactory1"> <!-- note the different name -->
4 <property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
5 <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
- 6 <property name="connection.url">jdbc:mysql://localhost:3306/mydb</property>
+ 6 <property name="connection.url">jdbc:mysql://dbhost1:3306/mydb</property>
7 <property name="connection.username">my_user</property>
8 <property name="connection.password">my_password</property>
9 <property name="hibernate.connection.shard_id">1</property> <!-- new -->
@@ -246,7 +246,8 @@
12 </hibernate-configuration>
]]></programlisting>
We'll skip the contents of shard2.hibernate.cfg.xml because the pattern should by now be obvious. We're
- giving each session factory a unique name via the name attribute of the session-factory element, and we're
+ giving each session factory a unique name via the name attribute of the session-factory element,
+ and we're associating each session factory with a different database server. We're
also giving each session factory a shard id. This is required. If you try to configure a
<classname>ShardedSessionFactory</classname> with a <classname>Configuration</classname>
object that does not have a shard id you'll get an error. At the moment we require that the shard id of one
Modified: shards/trunk/doc/reference/en/modules/limitations.xml
===================================================================
--- shards/trunk/doc/reference/en/modules/limitations.xml 2007-07-28 06:39:31 UTC (rev 12841)
+++ shards/trunk/doc/reference/en/modules/limitations.xml 2007-07-28 21:28:06 UTC (rev 12842)
@@ -12,7 +12,7 @@
<classname>ShardedCriteriaImpl</classname>, and <classname>ShardedQueryImpl</classname>.
</para>
</sect1>
- <sect1 id="shards-limitations-cross-shard" revision="1">
+ <sect1 id="shards-limitations-cross-shard" revision="2">
<title>Cross-Shard Object Graphs</title>
<para>
Hibernate Shards does not currently support cross-shard object graphs.
Added: shards/trunk/src/test/org/hibernate/shards/example/WeatherReport.java
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/example/WeatherReport.java (rev 0)
+++ shards/trunk/src/test/org/hibernate/shards/example/WeatherReport.java 2007-07-28 21:28:06 UTC (rev 12842)
@@ -0,0 +1,105 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+package org.hibernate.shards.example;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Date;
+
+/**
+ * Model object for our example app
+ *
+ * @author maxr(a)google.com (Max Ross)
+ */
+public class WeatherReport {
+ private BigInteger reportId;
+ private String continent;
+ private BigDecimal latitude;
+ private BigDecimal longitude;
+ private int temperature;
+ private Date reportTime;
+
+
+ public BigInteger getReportId() {
+ return reportId;
+ }
+
+ public void setReportId(BigInteger reportId) {
+ this.reportId = reportId;
+ }
+
+ public String getContinent() {
+ return continent;
+ }
+
+ public void setContinent(String continent) {
+ this.continent = continent;
+ }
+
+ public BigDecimal getLatitude() {
+ return latitude;
+ }
+
+ public void setLatitude(BigDecimal latitude) {
+ this.latitude = latitude;
+ }
+
+ public BigDecimal getLongitude() {
+ return longitude;
+ }
+
+ public void setLongitude(BigDecimal longitude) {
+ this.longitude = longitude;
+ }
+
+ public int getTemperature() {
+ return temperature;
+ }
+
+ public void setTemperature(int temperature) {
+ this.temperature = temperature;
+ }
+
+ public Date getReportTime() {
+ return reportTime;
+ }
+
+ public void setReportTime(Date reportTime) {
+ this.reportTime = reportTime;
+ }
+
+
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ WeatherReport that = (WeatherReport) o;
+
+ return !(reportId != null ? !reportId.equals(that.reportId)
+ : that.reportId != null);
+
+ }
+
+ public int hashCode() {
+ return (reportId != null ? reportId.hashCode() : 0);
+ }
+}
Added: shards/trunk/src/test/org/hibernate/shards/example/WeatherReportApp.java
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/example/WeatherReportApp.java (rev 0)
+++ shards/trunk/src/test/org/hibernate/shards/example/WeatherReportApp.java 2007-07-28 21:28:06 UTC (rev 12842)
@@ -0,0 +1,160 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+package org.hibernate.shards.example;
+
+import org.hibernate.Criteria;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.criterion.Restrictions;
+import org.hibernate.shards.ShardId;
+import org.hibernate.shards.ShardedConfiguration;
+import org.hibernate.shards.cfg.ConfigurationToShardConfigurationAdapter;
+import org.hibernate.shards.cfg.ShardConfiguration;
+import org.hibernate.shards.integration.IdGenType;
+import org.hibernate.shards.loadbalance.RoundRobinShardLoadBalancer;
+import org.hibernate.shards.strategy.ShardStrategy;
+import org.hibernate.shards.strategy.ShardStrategyFactory;
+import org.hibernate.shards.strategy.ShardStrategyImpl;
+import org.hibernate.shards.strategy.access.SequentialShardAccessStrategy;
+import org.hibernate.shards.strategy.access.ShardAccessStrategy;
+import org.hibernate.shards.strategy.resolution.AllShardsShardResolutionStrategy;
+import org.hibernate.shards.strategy.resolution.ShardResolutionStrategy;
+import org.hibernate.shards.strategy.selection.RoundRobinShardSelectionStrategy;
+import org.hibernate.shards.strategy.selection.ShardSelectionStrategy;
+import org.hibernate.shards.util.DatabaseUtils;
+
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * This is the sample app we use in the documentation.
+ *
+ * @author maxr(a)google.com (Max Ross)
+ */
+public class WeatherReportApp {
+
+ private SessionFactory sessionFactory;
+
+ public static void main(String[] args) throws Exception {
+ WeatherReportApp app = new WeatherReportApp();
+ app.run();
+ }
+
+ private void run() throws SQLException {
+ createSchema();
+ sessionFactory = createSessionFactory();
+
+ addData();
+
+ Session session = sessionFactory.openSession();
+ try {
+ Criteria crit = session.createCriteria(WeatherReport.class);
+ List count = crit.list();
+ System.out.println(count.size());
+ crit.add(Restrictions.gt("temperature", 33));
+ List reports = crit.list();
+ System.out.println(reports.size());
+ } finally {
+ session.close();
+ }
+ }
+
+ private void addData() {
+ Session session = sessionFactory.openSession();
+ try {
+ session.beginTransaction();
+ WeatherReport report = new WeatherReport();
+ report.setContinent("North America");
+ report.setLatitude(new BigDecimal(25));
+ report.setLongitude(new BigDecimal(30));
+ report.setReportTime(new Date());
+ report.setTemperature(44);
+ session.save(report);
+
+ report = new WeatherReport();
+ report.setContinent("Africa");
+ report.setLatitude(new BigDecimal(44));
+ report.setLongitude(new BigDecimal(99));
+ report.setReportTime(new Date());
+ report.setTemperature(31);
+ session.save(report);
+
+ report = new WeatherReport();
+ report.setContinent("Asia");
+ report.setLatitude(new BigDecimal(13));
+ report.setLongitude(new BigDecimal(12));
+ report.setReportTime(new Date());
+ report.setTemperature(104);
+ session.save(report);
+ session.getTransaction().commit();
+ } finally {
+ session.close();
+ }
+ }
+
+ private void createSchema() throws SQLException {
+ for(int i = 0; i < 3; i++) {
+ DatabaseUtils.destroyDatabase(i, IdGenType.SIMPLE);
+ DatabaseUtils.createDatabase(i, IdGenType.SIMPLE);
+ }
+
+ }
+
+ public SessionFactory createSessionFactory() {
+ Configuration prototypeConfig = new Configuration()
+ .configure(getClass().getResource("hibernate0.cfg.xml"));
+ prototypeConfig.addURL(getClass().getResource("weather.hbm.xml"));
+ List<ShardConfiguration> shardConfigs = new ArrayList<ShardConfiguration>();
+ shardConfigs.add(buildShardConfig(getClass().getResource("hibernate0.cfg.xml")));
+ shardConfigs.add(buildShardConfig(getClass().getResource("hibernate1.cfg.xml")));
+ shardConfigs.add(buildShardConfig(getClass().getResource("hibernate2.cfg.xml")));
+ ShardStrategyFactory shardStrategyFactory = buildShardStrategyFactory();
+ ShardedConfiguration shardedConfig = new ShardedConfiguration(
+ prototypeConfig,
+ shardConfigs,
+ shardStrategyFactory);
+ return shardedConfig.buildShardedSessionFactory();
+ }
+
+ ShardStrategyFactory buildShardStrategyFactory() {
+ return new ShardStrategyFactory() {
+ public ShardStrategy newShardStrategy(List<ShardId> shardIds) {
+ RoundRobinShardLoadBalancer loadBalancer
+ = new RoundRobinShardLoadBalancer(shardIds);
+ ShardSelectionStrategy pss = new RoundRobinShardSelectionStrategy(
+ loadBalancer);
+ ShardResolutionStrategy prs = new AllShardsShardResolutionStrategy(
+ shardIds);
+ ShardAccessStrategy pas = new SequentialShardAccessStrategy();
+ return new ShardStrategyImpl(pss, prs, pas);
+ }
+ };
+ }
+
+ ShardConfiguration buildShardConfig(URL configFile) {
+ Configuration config = new Configuration().configure(configFile);
+ return new ConfigurationToShardConfigurationAdapter(config);
+ }
+
+
+}
Added: shards/trunk/src/test/org/hibernate/shards/example/hibernate0.cfg.xml
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/example/hibernate0.cfg.xml (rev 0)
+++ shards/trunk/src/test/org/hibernate/shards/example/hibernate0.cfg.xml 2007-07-28 21:28:06 UTC (rev 12842)
@@ -0,0 +1,16 @@
+<!DOCTYPE hibernate-configuration PUBLIC
+ "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
+<hibernate-configuration>
+ <session-factory name="HibernateSessionFactory0">
+ <property name="dialect">org.hibernate.dialect.HSQLDialect</property>
+ <property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
+ <property name="connection.url">jdbc:hsqldb:mem:shard0</property>
+ <property name="connection.username">sa</property>
+ <property name="connection.password"></property>
+ <property name="hibernate.connection.shard_id">0</property>
+ <property name="hibernate.shard.enable_cross_shard_relationship_checks">
+ true
+ </property>
+ </session-factory>
+</hibernate-configuration>
Added: shards/trunk/src/test/org/hibernate/shards/example/hibernate1.cfg.xml
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/example/hibernate1.cfg.xml (rev 0)
+++ shards/trunk/src/test/org/hibernate/shards/example/hibernate1.cfg.xml 2007-07-28 21:28:06 UTC (rev 12842)
@@ -0,0 +1,16 @@
+<!DOCTYPE hibernate-configuration PUBLIC
+ "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
+<hibernate-configuration>
+ <session-factory name="HibernateSessionFactory1">
+ <property name="dialect">org.hibernate.dialect.HSQLDialect</property>
+ <property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
+ <property name="connection.url">jdbc:hsqldb:mem:shard1</property>
+ <property name="connection.username">sa</property>
+ <property name="connection.password"></property>
+ <property name="hibernate.connection.shard_id">1</property>
+ <property name="hibernate.shard.enable_cross_shard_relationship_checks">
+ true
+ </property>
+ </session-factory>
+</hibernate-configuration>
Added: shards/trunk/src/test/org/hibernate/shards/example/hibernate2.cfg.xml
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/example/hibernate2.cfg.xml (rev 0)
+++ shards/trunk/src/test/org/hibernate/shards/example/hibernate2.cfg.xml 2007-07-28 21:28:06 UTC (rev 12842)
@@ -0,0 +1,16 @@
+<!DOCTYPE hibernate-configuration PUBLIC
+ "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
+<hibernate-configuration>
+ <session-factory name="HibernateSessionFactory2">
+ <property name="dialect">org.hibernate.dialect.HSQLDialect</property>
+ <property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
+ <property name="connection.url">jdbc:hsqldb:mem:shard2</property>
+ <property name="connection.username">sa</property>
+ <property name="connection.password"></property>
+ <property name="hibernate.connection.shard_id">2</property>
+ <property name="hibernate.shard.enable_cross_shard_relationship_checks">
+ true
+ </property>
+ </session-factory>
+</hibernate-configuration>
Added: shards/trunk/src/test/org/hibernate/shards/example/weather.hbm.xml
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/example/weather.hbm.xml (rev 0)
+++ shards/trunk/src/test/org/hibernate/shards/example/weather.hbm.xml 2007-07-28 21:28:06 UTC (rev 12842)
@@ -0,0 +1,14 @@
+<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+<hibernate-mapping package="org.hibernate.shards.example">
+ <class name="WeatherReport" table="WEATHER_REPORT">
+ <id name="reportId" column="REPORT_ID" type="big_integer">
+ <generator class="org.hibernate.shards.id.ShardedUUIDGenerator"/>
+ </id>
+ <property name="continent" column="CONTINENT"/>
+ <property name="latitude" column="LATITUDE"/>
+ <property name="longitude" column="LONGITUDE"/>
+ <property name="temperature" column="TEMPERATURE"/>
+ <property name="reportTime" type="timestamp" column="REPORT_TIME"/>
+ </class>
+</hibernate-mapping>
Modified: shards/trunk/src/test/org/hibernate/shards/integration/BaseShardingIntegrationTestCase.java
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/integration/BaseShardingIntegrationTestCase.java 2007-07-28 06:39:31 UTC (rev 12841)
+++ shards/trunk/src/test/org/hibernate/shards/integration/BaseShardingIntegrationTestCase.java 2007-07-28 21:28:06 UTC (rev 12842)
@@ -44,16 +44,13 @@
import org.hibernate.shards.strategy.resolution.ShardResolutionStrategy;
import org.hibernate.shards.strategy.selection.RoundRobinShardSelectionStrategy;
import org.hibernate.shards.strategy.selection.ShardSelectionStrategy;
-import org.hibernate.shards.util.JdbcUtil;
+import org.hibernate.shards.util.DatabaseUtils;
import org.hibernate.shards.util.Lists;
import org.hibernate.shards.util.Maps;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
@@ -101,8 +98,8 @@
protected void setUp() throws Exception {
super.setUp();
for(int i = 0; i < getNumDatabases(); i++) {
- destroyDatabase(i);
- createDatabase(i);
+ DatabaseUtils.destroyDatabase(i, getIdGenType());
+ DatabaseUtils.createDatabase(i, getIdGenType());
}
Configuration prototypeConfig = buildPrototypeConfig();
List<ShardConfiguration> configurations = buildConfigurations();
@@ -212,54 +209,7 @@
super.tearDown();
}
- public Connection createConnection(int index) throws SQLException {
- DatabasePlatform dbPlatform = DatabasePlatformFactory.FACTORY.getDatabasePlatform();
- return
- DriverManager.getConnection(
- dbPlatform.getUrl(index),
- dbPlatform.getUser(),
- dbPlatform.getPassword());
- }
-
- private void destroyDatabase(int index) throws SQLException {
- DatabasePlatform dbPlatform = DatabasePlatformFactory.FACTORY.getDatabasePlatform();
- Connection conn = createConnection(index);
- try {
- for(String statement : dbPlatform.getDropTableStatements(getIdGenType())) {
- try {
- JdbcUtil.executeUpdate(conn, statement, false);
- } catch (SQLException sqle) {
- // not interested, keep moving
- }
- }
- } finally {
- conn.close();
- }
- }
-
- private void createDatabase(int index) throws SQLException {
- DatabasePlatform dbPlatform = DatabasePlatformFactory.FACTORY.getDatabasePlatform();
- Connection conn = createConnection(index);
- try {
- for(String statement : dbPlatform.getCreateTableStatements(getIdGenType())) {
- JdbcUtil.executeUpdate(conn, statement, false);
- }
- createDatabaseHook(conn);
- } finally {
- conn.close();
- }
- }
-
/**
- * Override if you want additional tables in your schema
- * @param conn the connection
- * @throws SQLException thrown if any of the operations performed with the
- * connection throws the same
- */
- protected void createDatabaseHook(Connection conn) throws SQLException {
- }
-
- /**
* Override if you want more than the default
* @return the number of databases
*/
Modified: shards/trunk/src/test/org/hibernate/shards/integration/platform/hsql/HSQLDatabasePlatform.java
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/integration/platform/hsql/HSQLDatabasePlatform.java 2007-07-28 06:39:31 UTC (rev 12841)
+++ shards/trunk/src/test/org/hibernate/shards/integration/platform/hsql/HSQLDatabasePlatform.java 2007-07-28 21:28:06 UTC (rev 12842)
@@ -55,6 +55,7 @@
,"CREATE TABLE Escalator (escalatorId DECIMAL(40,0) PRIMARY KEY, bottomFloorId DECIMAL(40,0), topFloorId DECIMAL(40,0))"
,"CREATE TABLE Person (personId DECIMAL(40,0) PRIMARY KEY, name VARCHAR(50), tenantId DECIMAL(40,0), officeId DECIMAL(40,0))"
,"CREATE TABLE IdIsBaseType (idIsBaseTypeId DECIMAL(40,0) PRIMARY KEY, value VARCHAR(50))"
+ ,"CREATE TABLE WEATHER_REPORT (REPORT_ID DECIMAL(40,0) PRIMARY KEY, CONTINENT VARCHAR(50), LATITUDE DECIMAL(10,2), LONGITUDE DECIMAL(10,2), TEMPERATURE DECIMAL(10,0), REPORT_TIME TIMESTAMP)"
);
protected static final List<String> DROP_TABLE_STATEMENTS = Lists.newArrayList(
Added: shards/trunk/src/test/org/hibernate/shards/util/DatabaseUtils.java
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/util/DatabaseUtils.java (rev 0)
+++ shards/trunk/src/test/org/hibernate/shards/util/DatabaseUtils.java 2007-07-28 21:28:06 UTC (rev 12842)
@@ -0,0 +1,71 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+package org.hibernate.shards.util;
+
+import org.hibernate.shards.integration.IdGenType;
+import org.hibernate.shards.integration.platform.DatabasePlatform;
+import org.hibernate.shards.integration.platform.DatabasePlatformFactory;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+/**
+ * @author maxr(a)google.com (Max Ross)
+ */
+public class DatabaseUtils {
+
+ public static Connection createConnection(int index) throws SQLException {
+ DatabasePlatform dbPlatform = DatabasePlatformFactory.FACTORY.getDatabasePlatform();
+ return
+ DriverManager.getConnection(
+ dbPlatform.getUrl(index),
+ dbPlatform.getUser(),
+ dbPlatform.getPassword());
+ }
+
+ public static void destroyDatabase(int index, IdGenType idGenType) throws SQLException {
+ DatabasePlatform dbPlatform = DatabasePlatformFactory.FACTORY.getDatabasePlatform();
+ Connection conn = createConnection(index);
+ try {
+ for(String statement : dbPlatform.getDropTableStatements(idGenType)) {
+ try {
+ JdbcUtil.executeUpdate(conn, statement, false);
+ } catch (SQLException sqle) {
+ // not interested, keep moving
+ }
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+ public static void createDatabase(int index, IdGenType idGenType) throws SQLException {
+ DatabasePlatform dbPlatform = DatabasePlatformFactory.FACTORY.getDatabasePlatform();
+ Connection conn = createConnection(index);
+ try {
+ for(String statement : dbPlatform.getCreateTableStatements(idGenType)) {
+ JdbcUtil.executeUpdate(conn, statement, false);
+ }
+ } finally {
+ conn.close();
+ }
+ }
+
+
+}
17 years, 5 months
Hibernate SVN: r12841 - shards/trunk/doc/reference/en.
by hibernate-commits@lists.jboss.org
Author: max.ross
Date: 2007-07-28 02:39:31 -0400 (Sat, 28 Jul 2007)
New Revision: 12841
Modified:
shards/trunk/doc/reference/en/master.xml
Log:
update master.xml for Beta2
Modified: shards/trunk/doc/reference/en/master.xml
===================================================================
--- shards/trunk/doc/reference/en/master.xml 2007-07-28 06:34:41 UTC (rev 12840)
+++ shards/trunk/doc/reference/en/master.xml 2007-07-28 06:39:31 UTC (rev 12841)
@@ -13,7 +13,7 @@
<title>Hibernate Shards</title>
<subtitle>Horizontal Partitioning With Hibernate</subtitle>
<subtitle>Reference Guide</subtitle>
- <releaseinfo>3.0.0.Beta1</releaseinfo>
+ <releaseinfo>3.0.0.Beta2</releaseinfo>
<mediaobject>
<imageobject>
<imagedata fileref="images/hibernate_logo_a.png" format="PNG"/>
17 years, 5 months
Hibernate SVN: r12840 - shards/trunk.
by hibernate-commits@lists.jboss.org
Author: max.ross
Date: 2007-07-28 02:34:41 -0400 (Sat, 28 Jul 2007)
New Revision: 12840
Modified:
shards/trunk/build.xml
shards/trunk/readme.txt
Log:
update readme.txt and build.xml for beta2
Modified: shards/trunk/build.xml
===================================================================
--- shards/trunk/build.xml 2007-07-28 06:30:11 UTC (rev 12839)
+++ shards/trunk/build.xml 2007-07-28 06:34:41 UTC (rev 12840)
@@ -16,7 +16,7 @@
<!-- Name of project and version, used to create filenames -->
<property name="Name" value="Hibernate Shards"/>
<property name="name" value="hibernate-shards"/>
- <property name="version" value="3.0.0.Beta1"/>
+ <property name="version" value="3.0.0.Beta2"/>
<property name="javadoc.packagenames" value="org.hibernate.shards.*"/>
<property name="copy.test" value="true"/>
<property name="javac.source" value="1.5"/>
Modified: shards/trunk/readme.txt
===================================================================
--- shards/trunk/readme.txt 2007-07-28 06:30:11 UTC (rev 12839)
+++ shards/trunk/readme.txt 2007-07-28 06:34:41 UTC (rev 12840)
@@ -1,6 +1,6 @@
Hibernate Shards
================
-Version: 3.0.0.Beta1, 19.03.2007
+Version: 3.0.0.Beta2, 28.07.2007
Description
-----------
@@ -26,12 +26,16 @@
Latest Documentation:
http://hibernate.org
+ http://shards.hibernate.org
Bug Reports:
Hibernate JIRA (preferred)
- hibernate-devel(a)lists.sourceforge.net
+Discussion:
+
+ hibernate-shards-dev(a)googlegroups.com
+
Free Technical Support:
http://forum.hibernate.org
17 years, 5 months
Hibernate SVN: r12839 - shards/trunk.
by hibernate-commits@lists.jboss.org
Author: max.ross
Date: 2007-07-28 02:30:11 -0400 (Sat, 28 Jul 2007)
New Revision: 12839
Modified:
shards/trunk/changelog.txt
Log:
update changelog for beta2
Modified: shards/trunk/changelog.txt
===================================================================
--- shards/trunk/changelog.txt 2007-07-28 04:20:45 UTC (rev 12838)
+++ shards/trunk/changelog.txt 2007-07-28 06:30:11 UTC (rev 12839)
@@ -1,6 +1,52 @@
Hibernate Shards Changelog
==========================
+
+3.0.0.Beta2 (7-28-2007)
+
+** Bug
+ * [HSHARDS-3] - setMaxResults method of Query is behaving wrong
+ * [HSHARDS-5] - Syntax errors in documentation code for Obtaining a ShardedSessionFactory
+ * [HSHARDS-7] - Typo
+ * [HSHARDS-8] - ConcatenateListsExitStrategy has null shard when using SequentialShardAccessStrategy
+ * [HSHARDS-10] - example weather.hbm.xml is wrong
+
+
+** Improvement
+ * [HSHARDS-6] - Shard configuration file names in documentation not consistant
+
+** New Feature
+ * [HSHARDS-36] - Support Hibernate Annotations
+ * [HSHARDS-38] - Support different second level cache prefixes across shards
+ * [HSHARDS-39] - Support average for Criteria
+
+
+** Task
+ * [HSHARDS-12] - ShardedSessionImpl.connection()
+ * [HSHARDS-13] - ShardedSessionImpl.load(Class theClass, Serializable id, LockMode lockMode);
+ * [HSHARDS-14] - ShardedSessionImpl.load(String entityName, Serializable id, LockMode lockMode);
+ * [HSHARDS-15] - ShardedSessionImpl.load(Class theClass, Serializable id);
+ * [HSHARDS-16] - ShardedSessionImpl.load(String entityName, Serializable id);
+ * [HSHARDS-17] - ShardedSessionImpl.load(Object object, Serializable id);
+ * [HSHARDS-18] - ShardedSessionImpl.replicate(Object obj, ReplicationMode replicationMode);
+ * [HSHARDS-19] - ShardedSessionImpl.replicate(String entityName, Object obj, ReplicationMode replicationMode);
+ * [HSHARDS-20] - ShardedSessionImpl.merge(Object obj);
+ * [HSHARDS-21] - ShardedSessionImpl.merge(String entityName, Object obj);
+ * [HSHARDS-22] - ShardedSessionImpl.persist(Object obj);
+ * [HSHARDS-23] - ShardedSessionImpl.persist(String entityName, Object obj);
+ * [HSHARDS-24] - ShardedSessionImpl.lock(Object obj, LockMode lockMode);
+ * [HSHARDS-25] - ShardedSessionImpl.lock(String entityName, Object obj, LockMode lockMode);
+ * [HSHARDS-26] - ShardedSessionImpl.refresh(Object obj, LockMode lockMode);
+ * [HSHARDS-27] - ShardedSessionImpl.refresh(Object obj);
+ * [HSHARDS-28] - ShardedSessionImpl.getCurrentLockMode(Object obj);
+ * [HSHARDS-30] - ShardedSessionImpl.createFilter(Object collection, String queryString);
+ * [HSHARDS-31] - ShardedSessionImpl.getEntityName(Object object);
+ * [HSHARDS-32] - ShardedSessionImpl.getSessionStatistics();
+ * [HSHARDS-33] - ShardedSessionImpl.disconnect();
+ * [HSHARDS-34] - ShardedSessionImpl.reconnect();
+
+
+
3.0.0.Beta1 (19-03-2007)
------------------------
17 years, 5 months
Hibernate SVN: r12838 - in shards/trunk/src: java/org/hibernate/shards/query and 6 other directories.
by hibernate-commits@lists.jboss.org
Author: max.ross
Date: 2007-07-28 00:20:45 -0400 (Sat, 28 Jul 2007)
New Revision: 12838
Modified:
shards/trunk/src/java/org/hibernate/shards/criteria/ExitOperationsCriteriaCollector.java
shards/trunk/src/java/org/hibernate/shards/query/QueryResult.java
shards/trunk/src/java/org/hibernate/shards/session/CrossShardRelationshipDetectingInterceptor.java
shards/trunk/src/java/org/hibernate/shards/session/ShardedSessionImpl.java
shards/trunk/src/java/org/hibernate/shards/stat/ShardedSessionStatistics.java
shards/trunk/src/java/org/hibernate/shards/strategy/exit/AggregateExitOperation.java
shards/trunk/src/java/org/hibernate/shards/strategy/exit/ExitOperationUtils.java
shards/trunk/src/java/org/hibernate/shards/strategy/exit/OrderExitOperation.java
shards/trunk/src/java/org/hibernate/shards/strategy/exit/ProjectionExitOperationFactory.java
shards/trunk/src/java/org/hibernate/shards/strategy/exit/ShardedAvgExitOperation.java
shards/trunk/src/test/org/hibernate/shards/integration/BaseShardingIntegrationTestCase.java
shards/trunk/src/test/org/hibernate/shards/integration/model/ModelCriteriaPermutedIntegrationTest.java
shards/trunk/src/test/org/hibernate/shards/integration/model/ModelPermutedIntegrationTest.java
shards/trunk/src/test/org/hibernate/shards/strategy/exit/AggregateExitOperationTest.java
shards/trunk/src/test/org/hibernate/shards/strategy/exit/FirstResultExitOperationTest.java
shards/trunk/src/test/org/hibernate/shards/strategy/exit/OrderExitOperationTest.java
Log:
cleaned up a bunch of compiler warnings
Modified: shards/trunk/src/java/org/hibernate/shards/criteria/ExitOperationsCriteriaCollector.java
===================================================================
--- shards/trunk/src/java/org/hibernate/shards/criteria/ExitOperationsCriteriaCollector.java 2007-07-28 03:20:18 UTC (rev 12837)
+++ shards/trunk/src/java/org/hibernate/shards/criteria/ExitOperationsCriteriaCollector.java 2007-07-28 04:20:45 UTC (rev 12838)
@@ -154,7 +154,7 @@
}
for(Order order : orders) {
- result = new OrderExitOperation(order, sessionFactoryImplementor).apply(result);
+ result = new OrderExitOperation(order).apply(result);
}
if (firstResult != null) {
result = new FirstResultExitOperation(firstResult).apply(result);
Modified: shards/trunk/src/java/org/hibernate/shards/query/QueryResult.java
===================================================================
--- shards/trunk/src/java/org/hibernate/shards/query/QueryResult.java 2007-07-28 03:20:18 UTC (rev 12837)
+++ shards/trunk/src/java/org/hibernate/shards/query/QueryResult.java 2007-07-28 04:20:45 UTC (rev 12838)
@@ -33,13 +33,13 @@
private final Map<Shard, List> resultMap = Maps.newHashMap();
- private final List entityList = Lists.newArrayList();
+ private final List<Object> entityList = Lists.newArrayList();
public Map<Shard, List> getResultMap() {
return Collections.unmodifiableMap(resultMap);
}
- public void add(Shard shard, List list) {
+ public void add(Shard shard, List<Object> list) {
resultMap.put(shard, list);
entityList.addAll(list);
}
@@ -49,7 +49,7 @@
entityList.addAll(result.getEntityList());
}
- public List getEntityList() {
+ public List<Object> getEntityList() {
return entityList;
}
Modified: shards/trunk/src/java/org/hibernate/shards/session/CrossShardRelationshipDetectingInterceptor.java
===================================================================
--- shards/trunk/src/java/org/hibernate/shards/session/CrossShardRelationshipDetectingInterceptor.java 2007-07-28 03:20:18 UTC (rev 12837)
+++ shards/trunk/src/java/org/hibernate/shards/session/CrossShardRelationshipDetectingInterceptor.java 2007-07-28 04:20:45 UTC (rev 12838)
@@ -75,7 +75,9 @@
if(collections == null) {
collections = Lists.newArrayList();
}
- collections.add((Collection<Object>) pair.getSecond());
+ @SuppressWarnings("unchecked")
+ Collection<Object> objColl = (Collection<Object>) pair.getSecond();
+ collections.add(objColl);
} else {
checkForConflictingShardId(entity.getClass().getName(), expectedShardId, pair.getSecond());
}
@@ -107,7 +109,7 @@
}
void checkForConflictingShardId(String classOfUpdatedObject, ShardId expectedShardId, Object associatedObject) {
- ShardId localShardId = null;
+ ShardId localShardId;
/*
* Here's something you wish you didn't need to know: If the associated
* object is an unitialized proxy and the object is not on the same
@@ -154,7 +156,9 @@
throws CallbackException {
ShardId expectedShardId = getAndRefreshExpectedShardId(((PersistentCollection)collection).getOwner());
Preconditions.checkNotNull(expectedShardId);
- checkIterable("<Unknown>", expectedShardId, (Iterable<Object>) collection);
+ @SuppressWarnings("unchecked")
+ Iterable<Object> iterable = (Iterable<Object>) collection;
+ checkIterable("<Unknown>", expectedShardId, iterable);
}
private ShardId getAndRefreshExpectedShardId(Object object) {
Modified: shards/trunk/src/java/org/hibernate/shards/session/ShardedSessionImpl.java
===================================================================
--- shards/trunk/src/java/org/hibernate/shards/session/ShardedSessionImpl.java 2007-07-28 03:20:18 UTC (rev 12837)
+++ shards/trunk/src/java/org/hibernate/shards/session/ShardedSessionImpl.java 2007-07-28 04:20:45 UTC (rev 12838)
@@ -710,7 +710,9 @@
if(collections == null) {
collections = Lists.newArrayList();
}
- collections.add((Collection<Object>) pair.getSecond());
+ @SuppressWarnings("unchecked")
+ Collection<Object> coll = (Collection<Object>) pair.getSecond();
+ collections.add(coll);
} else {
shardId = checkForConflictingShardId(shardId, obj.getClass(), pair.getSecond());
/**
Modified: shards/trunk/src/java/org/hibernate/shards/stat/ShardedSessionStatistics.java
===================================================================
--- shards/trunk/src/java/org/hibernate/shards/stat/ShardedSessionStatistics.java 2007-07-28 03:20:18 UTC (rev 12837)
+++ shards/trunk/src/java/org/hibernate/shards/stat/ShardedSessionStatistics.java 2007-07-28 04:20:45 UTC (rev 12838)
@@ -19,6 +19,8 @@
package org.hibernate.shards.stat;
import org.hibernate.Session;
+import org.hibernate.engine.CollectionKey;
+import org.hibernate.engine.EntityKey;
import org.hibernate.shards.Shard;
import org.hibernate.shards.engine.ShardedSessionImplementor;
import org.hibernate.shards.session.OpenSessionEvent;
@@ -69,18 +71,22 @@
return count;
}
- public Set getEntityKeys() {
- Set entityKeys = Sets.newHashSet();
+ public Set<EntityKey> getEntityKeys() {
+ Set<EntityKey> entityKeys = Sets.newHashSet();
for (SessionStatistics s : sessionStatistics) {
- entityKeys.addAll(s.getEntityKeys());
+ @SuppressWarnings("unchecked")
+ Set<EntityKey> shardEntityKeys = (Set<EntityKey>)s.getEntityKeys();
+ entityKeys.addAll(shardEntityKeys);
}
return entityKeys;
}
- public Set getCollectionKeys() {
- Set collectionKeys = Sets.newHashSet();
+ public Set<CollectionKey> getCollectionKeys() {
+ Set<CollectionKey> collectionKeys = Sets.newHashSet();
for (SessionStatistics s : sessionStatistics) {
- collectionKeys.addAll(s.getCollectionKeys());
+ @SuppressWarnings("unchecked")
+ Set<CollectionKey> shardCollectionKeys = (Set<CollectionKey>)s.getCollectionKeys();
+ collectionKeys.addAll(shardCollectionKeys);
}
return collectionKeys;
}
Modified: shards/trunk/src/java/org/hibernate/shards/strategy/exit/AggregateExitOperation.java
===================================================================
--- shards/trunk/src/java/org/hibernate/shards/strategy/exit/AggregateExitOperation.java 2007-07-28 03:20:18 UTC (rev 12837)
+++ shards/trunk/src/java/org/hibernate/shards/strategy/exit/AggregateExitOperation.java 2007-07-28 04:20:45 UTC (rev 12838)
@@ -21,8 +21,6 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.criterion.AggregateProjection;
-import org.hibernate.engine.SessionFactoryImplementor;
-import org.hibernate.shards.util.Preconditions;
import java.math.BigDecimal;
import java.util.Collections;
@@ -35,7 +33,6 @@
private final SupportedAggregations aggregate;
- private final SessionFactoryImplementor sessionFactoryImplementor;
private final String fieldName;
private final Log log = LogFactory.getLog(getClass());
@@ -58,9 +55,7 @@
}
- public AggregateExitOperation(AggregateProjection projection, SessionFactoryImplementor sessionFactoryImplementor) {
- Preconditions.checkNotNull(sessionFactoryImplementor);
- this.sessionFactoryImplementor = sessionFactoryImplementor;
+ public AggregateExitOperation(AggregateProjection projection) {
/**
* an aggregateProjection's toString returns
* min( ..., max( ..., sum( ..., or avg( ...
Modified: shards/trunk/src/java/org/hibernate/shards/strategy/exit/ExitOperationUtils.java
===================================================================
--- shards/trunk/src/java/org/hibernate/shards/strategy/exit/ExitOperationUtils.java 2007-07-28 03:20:18 UTC (rev 12837)
+++ shards/trunk/src/java/org/hibernate/shards/strategy/exit/ExitOperationUtils.java 2007-07-28 04:20:45 UTC (rev 12838)
@@ -40,12 +40,14 @@
return nonNullList;
}
- public static List<Comparable> getComparableList(List<Object> results) {
- return (List<Comparable>) (List) results; // I feel dirty
+ public static List<Comparable<Object>> getComparableList(List<Object> results) {
+ @SuppressWarnings("unchecked")
+ List<Comparable<Object>> result = (List<Comparable<Object>>) (List) results;
+ return result;
}
- public static Comparable getPropertyValue(Object obj, String propertyName) {
+ public static Comparable<Object> getPropertyValue(Object obj, String propertyName) {
/**
* TODO(maulik) respect the client's choice in how Hibernate accesses
* property values.
@@ -72,15 +74,17 @@
}
String[] methods = ("get" + propertyPath.toString().replaceAll("\\.", ".get")).split("\\.");
Object root = obj;
- for (int i=0; i < methods.length; i++) {
+ for (String method : methods) {
Class clazz = root.getClass();
- Method m = clazz.getMethod(methods[i]);
+ Method m = clazz.getMethod(method);
root = m.invoke(root);
if (root == null) {
break;
}
}
- return (Comparable) root;
+ @SuppressWarnings("unchecked")
+ Comparable<Object> result = (Comparable<Object>) root;
+ return result;
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
Modified: shards/trunk/src/java/org/hibernate/shards/strategy/exit/OrderExitOperation.java
===================================================================
--- shards/trunk/src/java/org/hibernate/shards/strategy/exit/OrderExitOperation.java 2007-07-28 03:20:18 UTC (rev 12837)
+++ shards/trunk/src/java/org/hibernate/shards/strategy/exit/OrderExitOperation.java 2007-07-28 04:20:45 UTC (rev 12838)
@@ -19,7 +19,6 @@
package org.hibernate.shards.strategy.exit;
import org.hibernate.criterion.Order;
-import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.shards.util.Preconditions;
import java.util.Collections;
@@ -32,28 +31,26 @@
public class OrderExitOperation implements ExitOperation {
private final Order order;
- private final SessionFactoryImplementor sessionFactoryImplementor;
private final String propertyName;
- public OrderExitOperation(Order order, SessionFactoryImplementor sessionFactoryImplementor) {
+ public OrderExitOperation(Order order) {
//TODO(maulik) support Ignore case!
Preconditions.checkState(order.toString().endsWith("asc") ||
order.toString().endsWith("desc"));
this.order = order;
this.propertyName = getSortingProperty(order);
- this.sessionFactoryImplementor = sessionFactoryImplementor;
}
public List<Object> apply(List<Object> results) {
- List nonNullList = ExitOperationUtils.getNonNullList(results);
- Comparator comparator = new Comparator() {
+ List<Object> nonNullList = ExitOperationUtils.getNonNullList(results);
+ Comparator<Object> comparator = new Comparator<Object>() {
public int compare(Object o1, Object o2) {
if (o1 == o2) {
return 0;
}
- Comparable o1Value = ExitOperationUtils.getPropertyValue(o1, propertyName);
- Comparable o2Value = ExitOperationUtils.getPropertyValue(o2, propertyName);
+ Comparable<Object> o1Value = ExitOperationUtils.getPropertyValue(o1, propertyName);
+ Comparable<Object> o2Value = ExitOperationUtils.getPropertyValue(o2, propertyName);
if (o1Value == null) {
return -1;
}
Modified: shards/trunk/src/java/org/hibernate/shards/strategy/exit/ProjectionExitOperationFactory.java
===================================================================
--- shards/trunk/src/java/org/hibernate/shards/strategy/exit/ProjectionExitOperationFactory.java 2007-07-28 03:20:18 UTC (rev 12837)
+++ shards/trunk/src/java/org/hibernate/shards/strategy/exit/ProjectionExitOperationFactory.java 2007-07-28 04:20:45 UTC (rev 12838)
@@ -42,7 +42,7 @@
return new RowCountExitOperation(projection);
}
if (projection instanceof AggregateProjection) {
- return new AggregateExitOperation((AggregateProjection) projection, sessionFactoryImplementor);
+ return new AggregateExitOperation((AggregateProjection) projection);
}
Modified: shards/trunk/src/java/org/hibernate/shards/strategy/exit/ShardedAvgExitOperation.java
===================================================================
--- shards/trunk/src/java/org/hibernate/shards/strategy/exit/ShardedAvgExitOperation.java 2007-07-28 03:20:18 UTC (rev 12837)
+++ shards/trunk/src/java/org/hibernate/shards/strategy/exit/ShardedAvgExitOperation.java 2007-07-28 04:20:45 UTC (rev 12838)
@@ -42,11 +42,12 @@
public List<Object> apply(List<Object> results) {
BigDecimal value = new BigDecimal(0.0);
BigDecimal count = new BigDecimal(0.0);
- for(Object obj : results) {
- Pair<Number, Number> pair = (Pair<Number, Number>) obj;
+ @SuppressWarnings("unchecked")
+ List<Pair<Double, Integer>> pairList = (List<Pair<Double, Integer>>) (List) results;
+ for(Pair<Double, Integer> pair : pairList) {
// we know the order of the pair (avg, count) by convention of ShardedAvgProjection
- value = value.add(new BigDecimal(pair.first.toString()));
- count = count.add(new BigDecimal(pair.second.toString()));
+ value = value.add(new BigDecimal(pair.first));
+ count = count.add(new BigDecimal(pair.second));
}
return Lists.newArrayList((Object)value.divide(count));
}
Modified: shards/trunk/src/test/org/hibernate/shards/integration/BaseShardingIntegrationTestCase.java
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/integration/BaseShardingIntegrationTestCase.java 2007-07-28 03:20:18 UTC (rev 12837)
+++ shards/trunk/src/test/org/hibernate/shards/integration/BaseShardingIntegrationTestCase.java 2007-07-28 04:20:45 UTC (rev 12838)
@@ -19,6 +19,9 @@
package org.hibernate.shards.integration;
import junit.framework.TestCase;
+
+import org.hibernate.Criteria;
+import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.shards.ShardId;
@@ -126,7 +129,7 @@
Map<Integer, Integer> virtualShardToShardMap = Maps.newHashMap();
if (isVirtualShardingEnabled()) {
for(int i = 0; i < getNumShards(); ++i) {
- virtualShardToShardMap.put(Integer.valueOf(i), Integer.valueOf(i % getNumDatabases()));
+ virtualShardToShardMap.put(i, i % getNumDatabases());
}
}
return virtualShardToShardMap;
@@ -249,12 +252,16 @@
/**
* Override if you want additional tables in your schema
+ * @param conn the connection
+ * @throws SQLException thrown if any of the operations performed with the
+ * connection throws the same
*/
protected void createDatabaseHook(Connection conn) throws SQLException {
}
/**
* Override if you want more than the default
+ * @return the number of databases
*/
protected int getNumDatabases() {
return perm.getNumDbs();
@@ -290,32 +297,26 @@
}
protected <T> T reloadAssertNotNull(Session session, T reloadMe) {
- T result = (T) reloadAll(session, reloadMe)[0];
+ T result = reload(session, reloadMe);
assertNotNull(result);
return result;
}
protected <T> T reload(Session session, T reloadMe) {
- return (T) reloadAll(session, reloadMe)[0];
- }
-
- protected Object[] reloadAll(Session session, Object... reloadMe) {
- List<Object> retVal = Lists.newArrayList();
- for(Object obj : reloadMe) {
- Class clazz = obj.getClass();
- String className = clazz.getSimpleName();
- try {
- Method m = clazz.getMethod("get" + className + "Id");
- retVal.add(session.get(clazz, (Serializable) m.invoke(obj)));
- } catch (NoSuchMethodException e) {
- throw new RuntimeException(e);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- } catch (InvocationTargetException e) {
- throw new RuntimeException(e);
- }
+ Class<?> clazz = reloadMe.getClass();
+ String className = clazz.getSimpleName();
+ try {
+ Method m = clazz.getMethod("get" + className + "Id");
+ @SuppressWarnings("unchecked")
+ T result = (T) get(session, clazz, (Serializable) m.invoke(reloadMe));
+ return result;
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e);
}
- return retVal.toArray();
}
protected ShardId getShardIdForObject(Object obj) {
@@ -361,6 +362,30 @@
// TODO(maxr) handel assertion failure separately so they get properly reported
}
}
+
+ protected <T> List<T> list(Criteria crit) {
+ @SuppressWarnings("unchecked")
+ List<T> result = crit.list();
+ return result;
+ }
+
+ protected <T> List<T> list(Query query) {
+ @SuppressWarnings("unchecked")
+ List<T> result = query.list();
+ return result;
+ }
+
+ protected <T> T uniqueResult(Criteria crit) {
+ @SuppressWarnings("unchecked")
+ T result = (T) crit.uniqueResult();
+ return result;
+ }
+
+ protected <T> T get(Session session, Class<?> clazz, Serializable id) {
+ @SuppressWarnings("unchecked")
+ T result = (T) session.get(clazz, id);
+ return result;
+ }
}
Modified: shards/trunk/src/test/org/hibernate/shards/integration/model/ModelCriteriaPermutedIntegrationTest.java
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/integration/model/ModelCriteriaPermutedIntegrationTest.java 2007-07-28 03:20:18 UTC (rev 12837)
+++ shards/trunk/src/test/org/hibernate/shards/integration/model/ModelCriteriaPermutedIntegrationTest.java 2007-07-28 04:20:45 UTC (rev 12838)
@@ -281,13 +281,5 @@
List<Office> answer = Lists.newArrayList(b2f1o1, b1f3o1, b1f3o2);
assertTrue(answer.equals(l));
}
-
- private <T> List<T> list(Criteria crit) {
- return crit.list();
- }
-
- private <T> T uniqueResult(Criteria crit) {
- return (T) crit.uniqueResult();
- }
}
Modified: shards/trunk/src/test/org/hibernate/shards/integration/model/ModelPermutedIntegrationTest.java
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/integration/model/ModelPermutedIntegrationTest.java 2007-07-28 03:20:18 UTC (rev 12837)
+++ shards/trunk/src/test/org/hibernate/shards/integration/model/ModelPermutedIntegrationTest.java 2007-07-28 04:20:45 UTC (rev 12838)
@@ -108,7 +108,7 @@
buildings.add(b);
}
commitAndResetSession();
- List<Integer> counts = session.createCriteria(Building.class).setProjection(Projections.rowCount()).list();
+ List<Integer> counts = list(session.createCriteria(Building.class).setProjection(Projections.rowCount()));
int total = 0;
for(Integer count : counts) {
total += count;
@@ -656,7 +656,7 @@
for(int i=0; i<getNumShards(); i++) {
saveBuilding("building-"+i);
}
- List<Building> buildings = session.createQuery("from Building").list();
+ List<Building> buildings = list(session.createQuery("from Building"));
assertEquals(getNumShards(), buildings.size());
resetSession();
@@ -686,7 +686,7 @@
// do we only search certain shards?
// we should only get back the buildings that were on shard 0, i.e. a single building
Session sessionWithParticularShards = ssfWithParticularShards.openSession();
- List<Building> buildingsFromDesiredShards = sessionWithParticularShards.createQuery("from Building").list();
+ List<Building> buildingsFromDesiredShards = list(sessionWithParticularShards.createQuery("from Building"));
if (!isVirtualShardingEnabled()) {
assertEquals(1, buildingsFromDesiredShards.size());
Modified: shards/trunk/src/test/org/hibernate/shards/strategy/exit/AggregateExitOperationTest.java
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/strategy/exit/AggregateExitOperationTest.java 2007-07-28 03:20:18 UTC (rev 12837)
+++ shards/trunk/src/test/org/hibernate/shards/strategy/exit/AggregateExitOperationTest.java 2007-07-28 04:20:45 UTC (rev 12838)
@@ -19,6 +19,7 @@
package org.hibernate.shards.strategy.exit;
import junit.framework.TestCase;
+
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
@@ -76,38 +77,38 @@
public void testCtor() throws Exception {
try {
- new AggregateExitOperation(new AvgProjection("foo"), new SessionFactoryMock());
+ new AggregateExitOperation(new AvgProjection("foo"));
fail();
} catch (IllegalArgumentException e) {
// good
}
try {
- new AggregateExitOperation(new AvgProjection("foo"), new SessionFactoryDefaultMock());
+ new AggregateExitOperation(new AvgProjection("foo"));
fail();
} catch (IllegalArgumentException e) {
// good
}
- new AggregateExitOperation(Projections.max("foo"), new SessionFactoryDefaultMock());
- new AggregateExitOperation(Projections.min("foo"), new SessionFactoryDefaultMock());
- new AggregateExitOperation(Projections.sum("foo"), new SessionFactoryDefaultMock());
+ new AggregateExitOperation(Projections.max("foo"));
+ new AggregateExitOperation(Projections.min("foo"));
+ new AggregateExitOperation(Projections.sum("foo"));
}
public void testSum() throws Exception {
- AggregateExitOperation exitOp = new AggregateExitOperation(Projections.sum("value"), new SessionFactoryMock());
+ AggregateExitOperation exitOp = new AggregateExitOperation(Projections.sum("value"));
List<Object> result = exitOp.apply(data);
assertEquals(new BigDecimal(11.0), (BigDecimal)result.get(0));
}
public void testMax() throws Exception {
- AggregateExitOperation exitOp = new AggregateExitOperation(Projections.max("value"), new SessionFactoryMock());
+ AggregateExitOperation exitOp = new AggregateExitOperation(Projections.max("value"));
List<Object> result = exitOp.apply(data);
assertEquals(5, ((MyInt)result.get(0)).getValue());
}
public void testMin() throws Exception {
- AggregateExitOperation exitOp = new AggregateExitOperation(Projections.min("value"), new SessionFactoryMock());
+ AggregateExitOperation exitOp = new AggregateExitOperation(Projections.min("value"));
List<Object> result = exitOp.apply(data);
assertEquals(0, ((MyInt)result.get(0)).getValue());
Modified: shards/trunk/src/test/org/hibernate/shards/strategy/exit/FirstResultExitOperationTest.java
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/strategy/exit/FirstResultExitOperationTest.java 2007-07-28 03:20:18 UTC (rev 12837)
+++ shards/trunk/src/test/org/hibernate/shards/strategy/exit/FirstResultExitOperationTest.java 2007-07-28 04:20:45 UTC (rev 12838)
@@ -20,6 +20,7 @@
import junit.framework.TestCase;
+
import org.hibernate.shards.util.Lists;
import java.util.List;
@@ -56,7 +57,8 @@
List<Object> objects = exitOp.apply(list);
assertTrue(objects.isEmpty());
- list = Lists.newArrayList(null, null, null);
+ Object nullObj = null;
+ list = Lists.newArrayList(nullObj, nullObj, nullObj);
objects = exitOp.apply(list);
assertTrue(objects.isEmpty());
Modified: shards/trunk/src/test/org/hibernate/shards/strategy/exit/OrderExitOperationTest.java
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/strategy/exit/OrderExitOperationTest.java 2007-07-28 03:20:18 UTC (rev 12837)
+++ shards/trunk/src/test/org/hibernate/shards/strategy/exit/OrderExitOperationTest.java 2007-07-28 04:20:45 UTC (rev 12838)
@@ -19,6 +19,7 @@
package org.hibernate.shards.strategy.exit;
import junit.framework.TestCase;
+
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
@@ -102,7 +103,7 @@
public void testApply() throws Exception {
Order order = Order.asc("value");
- OrderExitOperation oeo = new OrderExitOperation(order, new SessionFactoryMock());
+ OrderExitOperation oeo = new OrderExitOperation(order);
List unShuffledList = oeo.apply(shuffledList);
assertTrue(nonNullData.equals(unShuffledList));
@@ -112,8 +113,8 @@
Order orderValue = Order.asc("value");
Order orderName = Order.desc("name");
- OrderExitOperation oeoValue = new OrderExitOperation(orderValue, new SessionFactoryMock());
- OrderExitOperation oeoName = new OrderExitOperation(orderName, new SessionFactoryMock());
+ OrderExitOperation oeoValue = new OrderExitOperation(orderValue);
+ OrderExitOperation oeoName = new OrderExitOperation(orderName);
List<MyInt> answer =
Lists.newArrayList(
17 years, 5 months
Hibernate SVN: r12837 - shards/trunk/src/test/org/hibernate/shards/integration.
by hibernate-commits@lists.jboss.org
Author: max.ross
Date: 2007-07-27 23:20:18 -0400 (Fri, 27 Jul 2007)
New Revision: 12837
Modified:
shards/trunk/src/test/org/hibernate/shards/integration/DbAccessPermutedIntegrationTest.java
Log:
Got rid of use of deprecated method.
Modified: shards/trunk/src/test/org/hibernate/shards/integration/DbAccessPermutedIntegrationTest.java
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/integration/DbAccessPermutedIntegrationTest.java 2007-07-28 03:10:55 UTC (rev 12836)
+++ shards/trunk/src/test/org/hibernate/shards/integration/DbAccessPermutedIntegrationTest.java 2007-07-28 03:20:18 UTC (rev 12837)
@@ -18,15 +18,14 @@
package org.hibernate.shards.integration;
+import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.shards.engine.ShardedSessionFactoryImplementor;
-import org.hibernate.shards.util.JdbcStrategy;
-import org.hibernate.shards.util.JdbcUtil;
-import java.sql.Connection;
-import java.sql.ResultSet;
+import java.math.BigDecimal;
import java.sql.SQLException;
+import java.util.List;
import java.util.Set;
/**
@@ -46,36 +45,33 @@
private void testShard(SessionFactory sf) throws SQLException {
Session session = sf.openSession();
try {
- Connection conn = session.connection();
- insertRecord(conn);
- updateRecord(conn);
- selectRecord(conn);
- deleteRecord(conn);
+ insertRecord(session);
+ updateRecord(session);
+ selectRecord(session);
+ deleteRecord(session);
} finally {
session.close();
}
}
- private void insertRecord(Connection conn) throws SQLException {
- assertEquals(1, JdbcUtil.executeUpdate(conn, "INSERT INTO sample_table(id, str_col) values (0, 'yam')", false));
+ private void insertRecord(Session session) throws SQLException {
+ assertEquals(1, session.createSQLQuery("INSERT INTO sample_table(id, str_col) values (0, 'yam')").executeUpdate());
}
- private void updateRecord(Connection conn) throws SQLException {
- assertEquals(1, JdbcUtil.executeUpdate(conn, "UPDATE sample_table set str_col = 'max' where id = 0", false));
+ private void updateRecord(Session session) throws SQLException {
+ assertEquals(1, session.createSQLQuery("UPDATE sample_table set str_col = 'max' where id = 0").executeUpdate());
}
- private void selectRecord(Connection conn) throws SQLException {
- JdbcStrategy strat = new JdbcStrategy() {
- public void extractData(ResultSet rs) throws SQLException {
- assertEquals(0, rs.getInt("id"));
- assertEquals("max", rs.getString("str_col"));
- assertFalse(rs.next());
- }
- };
- JdbcUtil.executeJdbcQuery(conn, "select id, str_col from sample_table where id = 0", strat, false);
+ private void selectRecord(Session session) throws SQLException {
+ SQLQuery query = session.createSQLQuery("select id, str_col from sample_table where id = 0");
+ List results = query.list();
+ assertEquals(1, results.size());
+ Object[] result = (Object[]) results.get(0);
+ assertEquals(new BigDecimal(0), result[0]);
+ assertEquals("max", result[1]);
}
- private void deleteRecord(Connection conn) throws SQLException {
- assertEquals(1, JdbcUtil.executeUpdate(conn, "DELETE from sample_table where id = 0", false));
+ private void deleteRecord(Session session) throws SQLException {
+ assertEquals(1, session.createSQLQuery("DELETE from sample_table where id = 0").executeUpdate());
}
}
17 years, 5 months
Hibernate SVN: r12836 - in shards/trunk/src: java/org/hibernate/shards/strategy/exit and 7 other directories.
by hibernate-commits@lists.jboss.org
Author: max.ross
Date: 2007-07-27 23:10:55 -0400 (Fri, 27 Jul 2007)
New Revision: 12836
Added:
shards/trunk/src/java/org/hibernate/shards/strategy/exit/AvgResultsExitOperation.java
shards/trunk/src/test/org/hibernate/shards/strategy/exit/AvgResultsExitOperationTest.java
Modified:
shards/trunk/src/java/org/hibernate/shards/criteria/ExitOperationsCriteriaCollector.java
shards/trunk/src/java/org/hibernate/shards/criteria/ShardedCriteriaImpl.java
shards/trunk/src/test/org/hibernate/shards/NonPermutedTests.java
shards/trunk/src/test/org/hibernate/shards/integration/model/ModelCriteriaPermutedIntegrationTest.java
shards/trunk/src/test/org/hibernate/shards/integration/model/ModelDataFactory.java
shards/trunk/src/test/org/hibernate/shards/integration/platform/hsql/HSQLDatabasePlatform.java
shards/trunk/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings-shardedTableHiLo.hbm.xml
shards/trunk/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings-shardedUUID.hbm.xml
shards/trunk/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings.hbm.xml
shards/trunk/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings-shardedTableHiLo.hbm.xml
shards/trunk/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings-shardedUUID.hbm.xml
shards/trunk/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings.hbm.xml
shards/trunk/src/test/org/hibernate/shards/model/Floor.java
Log:
HSHARDS-39
Implement avg projection
Modified: shards/trunk/src/java/org/hibernate/shards/criteria/ExitOperationsCriteriaCollector.java
===================================================================
--- shards/trunk/src/java/org/hibernate/shards/criteria/ExitOperationsCriteriaCollector.java 2007-07-27 12:06:55 UTC (rev 12835)
+++ shards/trunk/src/java/org/hibernate/shards/criteria/ExitOperationsCriteriaCollector.java 2007-07-28 03:10:55 UTC (rev 12836)
@@ -26,6 +26,7 @@
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.RowCountProjection;
import org.hibernate.engine.SessionFactoryImplementor;
+import org.hibernate.shards.strategy.exit.AvgResultsExitOperation;
import org.hibernate.shards.strategy.exit.DistinctExitOperation;
import org.hibernate.shards.strategy.exit.ExitOperationsCollector;
import org.hibernate.shards.strategy.exit.FirstResultExitOperation;
@@ -162,14 +163,16 @@
result = new MaxResultsExitOperation(maxResults).apply(result);
}
- ProjectionExitOperationFactory factory = ProjectionExitOperationFactory
- .getFactory();
+ ProjectionExitOperationFactory factory =
+ ProjectionExitOperationFactory.getFactory();
if (rowCountProjection != null) {
result = factory.getProjectionExitOperation(rowCountProjection, sessionFactoryImplementor).apply(result);
}
- // TODO(maulik) average should go here
+ if (avgProjection != null) {
+ result = new AvgResultsExitOperation().apply(result);
+ }
// min, max, sum
if (aggregateProjection != null) {
Modified: shards/trunk/src/java/org/hibernate/shards/criteria/ShardedCriteriaImpl.java
===================================================================
--- shards/trunk/src/java/org/hibernate/shards/criteria/ShardedCriteriaImpl.java 2007-07-27 12:06:55 UTC (rev 12835)
+++ shards/trunk/src/java/org/hibernate/shards/criteria/ShardedCriteriaImpl.java 2007-07-28 03:10:55 UTC (rev 12836)
@@ -26,9 +26,12 @@
import org.hibernate.LockMode;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
+import org.hibernate.criterion.AvgProjection;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
+import org.hibernate.criterion.ProjectionList;
+import org.hibernate.criterion.Projections;
import org.hibernate.shards.Shard;
import org.hibernate.shards.ShardOperation;
import org.hibernate.shards.strategy.access.ShardAccessStrategy;
@@ -126,9 +129,30 @@
public Criteria setProjection(Projection projection) {
criteriaCollector.addProjection(projection);
+ if(projection instanceof AvgProjection) {
+ setAvgProjection(projection);
+ }
+ // TODO - handle ProjectionList
return this;
}
+ private void setAvgProjection(Projection projection) {
+ // We need to modify the query to pull back not just the average but also
+ // the count. We'll do this by creating a ProjectionList with both the
+ // average and the row count.
+ ProjectionList projectionList = Projections.projectionList();
+ projectionList.add(projection);
+ projectionList.add(Projections.rowCount());
+ CriteriaEvent event = new SetProjectionEvent(projectionList);
+ for (Shard shard : shards) {
+ if (shard.getCriteriaById(criteriaId) != null) {
+ shard.getCriteriaById(criteriaId).setProjection(projectionList);
+ } else {
+ shard.addCriteriaEvent(criteriaId, event);
+ }
+ }
+ }
+
public Criteria add(Criterion criterion) {
CriteriaEvent event = new AddCriterionEvent(criterion);
for (Shard shard : shards) {
Added: shards/trunk/src/java/org/hibernate/shards/strategy/exit/AvgResultsExitOperation.java
===================================================================
--- shards/trunk/src/java/org/hibernate/shards/strategy/exit/AvgResultsExitOperation.java (rev 0)
+++ shards/trunk/src/java/org/hibernate/shards/strategy/exit/AvgResultsExitOperation.java 2007-07-28 03:10:55 UTC (rev 12836)
@@ -0,0 +1,97 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+package org.hibernate.shards.strategy.exit;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.shards.util.Pair;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Performs post-processing on a result set that has had an average projection
+ * applied.
+ *
+ * This may not yield the exact same result as you'd get if you ran the query
+ * on a single shard because there seems to be some platform-specific wiggle.
+ * Here's a specific example:
+ * On hsqldb, if you have a column of type DECIMAL(10, 4) and you ask for the
+ * average of the values in that column, you get the floor of the result.
+ * On MySQL, if you have a column of the same type, you get a result back with
+ * the expected precision. So, um, just be careful.
+ *
+ * @author maxr(a)google.com (Max Ross)
+ */
+public class AvgResultsExitOperation implements ExitOperation {
+
+ private final Log log = LogFactory.getLog(getClass());
+
+ public List<Object> apply(List<Object> results) {
+ List<Object> nonNullResults = ExitOperationUtils.getNonNullList(results);
+ Double total = null;
+ int numResults = 0;
+ for(Object result : nonNullResults) {
+ /**
+ * We expect all entries to be Object arrays.
+ * the first entry in the array is the average (a double)
+ * the second entry in the array is the number of rows that were examined
+ * to arrive at the average.
+ */
+ Pair<Double, Integer> pair = getResultPair(result);
+ Double shardAvg = pair.first;
+ if(shardAvg == null) {
+ // if there's no result from this shard it doesn't go into the
+ // calculation. This is consistent with how avg is implemented
+ // in the database
+ continue;
+ }
+ int shardResults = pair.second;
+ Double shardTotal = shardAvg * shardResults;
+ if(total == null) {
+ total = shardTotal;
+ } else {
+ total += shardTotal;
+ }
+ numResults += shardResults;
+ }
+ if(numResults == 0 || total == null) {
+ return Collections.singletonList(null);
+ }
+ return Collections.<Object>singletonList(total / numResults);
+ }
+
+ private Pair<Double, Integer> getResultPair(Object result) {
+ if(!(result instanceof Object[])) {
+ final String msg =
+ "Wrong type in result list. Expected " + Object[].class +
+ " but found " + result.getClass();
+ log.error(msg);
+ throw new IllegalStateException(msg);
+ }
+ Object[] resultArr = (Object[]) result;
+ if(resultArr.length != 2) {
+ final String msg =
+ "Result array is wrong size. Expected 2 " +
+ " but found " + resultArr.length;
+ log.error(msg);
+ throw new IllegalStateException(msg);
+ }
+ return Pair.of((Double) resultArr[0], (Integer) resultArr[1]);
+ }
+}
Modified: shards/trunk/src/test/org/hibernate/shards/NonPermutedTests.java
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/NonPermutedTests.java 2007-07-27 12:06:55 UTC (rev 12835)
+++ shards/trunk/src/test/org/hibernate/shards/NonPermutedTests.java 2007-07-28 03:10:55 UTC (rev 12836)
@@ -18,6 +18,7 @@
package org.hibernate.shards;
import junit.framework.TestCase;
+
import org.hibernate.shards.util.Lists;
import java.util.Collections;
@@ -117,6 +118,7 @@
classes.add(org.hibernate.shards.strategy.access.ParallelShardOperationCallableTest.class);
classes.add(org.hibernate.shards.strategy.access.StartAwareFutureTaskTest.class);
classes.add(org.hibernate.shards.strategy.exit.AggregateExitOperationTest.class);
+ classes.add(org.hibernate.shards.strategy.exit.AvgResultsExitOperationTest.class);
classes.add(org.hibernate.shards.strategy.exit.ExitOperationUtilsTest.class);
classes.add(org.hibernate.shards.strategy.exit.FirstNonNullResultExitStrategyTest.class);
classes.add(org.hibernate.shards.strategy.exit.FirstResultExitOperationTest.class);
Modified: shards/trunk/src/test/org/hibernate/shards/integration/model/ModelCriteriaPermutedIntegrationTest.java
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/integration/model/ModelCriteriaPermutedIntegrationTest.java 2007-07-27 12:06:55 UTC (rev 12835)
+++ shards/trunk/src/test/org/hibernate/shards/integration/model/ModelCriteriaPermutedIntegrationTest.java 2007-07-28 03:10:55 UTC (rev 12836)
@@ -53,9 +53,12 @@
super.setUp();
session.beginTransaction();
b1 = ModelDataFactory.building("b1");
- b1f1 = ModelDataFactory.floor(b1, 1);
- b1f2 = ModelDataFactory.floor(b1, 2);
- b1f3 = ModelDataFactory.floor(b1, 3);
+ // because of the fuzziness in how avg gets computed on hsqldb
+ // we need to make sure the per-shard avg is a round number, otherwise
+ // our test will fail
+ b1f1 = ModelDataFactory.floor(b1, 1, new BigDecimal(10.00));
+ b1f2 = ModelDataFactory.floor(b1, 2, new BigDecimal(20.00));
+ b1f3 = ModelDataFactory.floor(b1, 3, new BigDecimal(30.00));
b1f3o1 = ModelDataFactory.office("NOT LAHGE", b1f3);
b1f3o2 = ModelDataFactory.office("LAHGE", b1f3);
session.save(b1);
@@ -63,7 +66,7 @@
session.beginTransaction();
b2 = ModelDataFactory.building("b2");
- b2f1 = ModelDataFactory.floor(b2, 1);
+ b2f1 = ModelDataFactory.floor(b2, 1, new BigDecimal(20.00));
b2f1o1 = ModelDataFactory.office("LAHGE", b2f1);
session.save(b2);
session.getTransaction().commit();
@@ -220,7 +223,7 @@
assertEquals(2, l.size());
}
- public void testProjection() {
+ public void testRowCountProjection() {
Criteria crit = session.createCriteria(Building.class).setProjection(Projections.rowCount());
Criteria floorCrit = crit.createCriteria("floors");
Criteria officeCrit = floorCrit.createCriteria("offices");
@@ -235,6 +238,14 @@
assertEquals(2, total);
}
+ public void testAvgProjection() {
+ Criteria crit = session.createCriteria(Floor.class).setProjection(Projections.avg("squareFeet"));
+ List<Double> l = list(crit);
+ assertEquals(1, l.size());
+ assertEquals(20.0, l.get(0));
+ }
+
+
public void testMaxResults() throws Exception {
Criteria crit = session.createCriteria(Building.class).setMaxResults(1);
assertEquals(1, list(crit).size());
Modified: shards/trunk/src/test/org/hibernate/shards/integration/model/ModelDataFactory.java
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/integration/model/ModelDataFactory.java 2007-07-27 12:06:55 UTC (rev 12835)
+++ shards/trunk/src/test/org/hibernate/shards/integration/model/ModelDataFactory.java 2007-07-28 03:10:55 UTC (rev 12836)
@@ -27,6 +27,7 @@
import org.hibernate.shards.model.Tenant;
import org.hibernate.shards.model.Window;
+import java.math.BigDecimal;
import java.util.List;
/**
@@ -53,14 +54,19 @@
}
public static Floor floor(Building b, int number) {
- return floor(b, number, null, null);
+ return floor(b, number, null, null, null);
}
- public static Floor floor(Building b, int number, Escalator up, Escalator down) {
+ public static Floor floor(Building b, int number, BigDecimal squareFeet) {
+ return floor(b, number, squareFeet, null, null);
+ }
+
+ public static Floor floor(Building b, int number, BigDecimal squareFeet, Escalator up, Escalator down) {
Floor f = new Floor();
f.setBuilding(b);
b.getFloors().add(f);
f.setNumber(number);
+ f.setSquareFeet(squareFeet);
f.setGoingDown(down);
f.setGoingUp(up);
return f;
Modified: shards/trunk/src/test/org/hibernate/shards/integration/platform/hsql/HSQLDatabasePlatform.java
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/integration/platform/hsql/HSQLDatabasePlatform.java 2007-07-27 12:06:55 UTC (rev 12835)
+++ shards/trunk/src/test/org/hibernate/shards/integration/platform/hsql/HSQLDatabasePlatform.java 2007-07-28 03:10:55 UTC (rev 12836)
@@ -46,7 +46,7 @@
,"INSERT INTO hibernate_unique_key(next_hi) VALUES(1)"
,"CREATE TABLE Elevator (elevatorId DECIMAL(40,0) PRIMARY KEY, buildingId DECIMAL(40,0))"
,"CREATE TABLE Building (buildingId DECIMAL(40,0) PRIMARY KEY, name VARCHAR(50))"
- ,"CREATE TABLE Floor (floorId DECIMAL(40,0) PRIMARY KEY, buildingId DECIMAL(40,0), upEscalatorId DECIMAL(40,0), downEscalatorId DECIMAL(40,0), number DECIMAL(40,0))"
+ ,"CREATE TABLE Floor (floorId DECIMAL(40,0) PRIMARY KEY, buildingId DECIMAL(40,0), upEscalatorId DECIMAL(40,0), downEscalatorId DECIMAL(40,0), number DECIMAL(40,0), squareFeet DECIMAL(40, 4))"
,"CREATE TABLE Tenant (tenantId DECIMAL(40,0) PRIMARY KEY, name VARCHAR(50))"
,"CREATE TABLE BuildingTenant (buildingId DECIMAL(40,0), tenantId DECIMAL(40,0), PRIMARY KEY(buildingId, tenantId))"
,"CREATE TABLE Office (officeId DECIMAL(40,0) PRIMARY KEY, floorId DECIMAL(40,0), label VARCHAR(50), windowId DECIMAL(40,0))"
Modified: shards/trunk/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings-shardedTableHiLo.hbm.xml
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings-shardedTableHiLo.hbm.xml 2007-07-27 12:06:55 UTC (rev 12835)
+++ shards/trunk/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings-shardedTableHiLo.hbm.xml 2007-07-28 03:10:55 UTC (rev 12836)
@@ -109,6 +109,7 @@
<generator class="org.hibernate.shards.id.ShardedTableHiLoGenerator"/>
</id>
<property name="number" not-null="true"/>
+ <property name="squareFeet" not-null="false"/>
<many-to-one name="goingUp" column="upEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
<many-to-one name="goingDown" column="downEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
<many-to-one name="building" column="buildingId" not-null="true" class="Building"/>
Modified: shards/trunk/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings-shardedUUID.hbm.xml
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings-shardedUUID.hbm.xml 2007-07-27 12:06:55 UTC (rev 12835)
+++ shards/trunk/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings-shardedUUID.hbm.xml 2007-07-28 03:10:55 UTC (rev 12836)
@@ -108,6 +108,7 @@
<generator class="org.hibernate.shards.id.ShardedUUIDGenerator"/>
</id>
<property name="number" not-null="true"/>
+ <property name="squareFeet" not-null="false"/>
<many-to-one name="goingUp" column="upEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
<many-to-one name="goingDown" column="downEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
<many-to-one name="building" column="buildingId" not-null="true" class="Building"/>
Modified: shards/trunk/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings.hbm.xml
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings.hbm.xml 2007-07-27 12:06:55 UTC (rev 12835)
+++ shards/trunk/src/test/org/hibernate/shards/integration/platform/hsql/config/mappings.hbm.xml 2007-07-28 03:10:55 UTC (rev 12836)
@@ -108,6 +108,7 @@
<generator class="org.hibernate.shards.id.UUIDBigIntGenerator"/>
</id>
<property name="number" not-null="true"/>
+ <property name="squareFeet" not-null="false"/>
<many-to-one name="goingUp" column="upEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
<many-to-one name="goingDown" column="downEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
<many-to-one name="building" column="buildingId" not-null="true" class="Building"/>
Modified: shards/trunk/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings-shardedTableHiLo.hbm.xml
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings-shardedTableHiLo.hbm.xml 2007-07-27 12:06:55 UTC (rev 12835)
+++ shards/trunk/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings-shardedTableHiLo.hbm.xml 2007-07-28 03:10:55 UTC (rev 12836)
@@ -108,6 +108,7 @@
<generator class="org.hibernate.shards.id.ShardedTableHiLoGenerator"/>
</id>
<property name="number" not-null="true"/>
+ <property name="squareFeet" not-null="false"/>
<many-to-one name="goingUp" column="upEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
<many-to-one name="goingDown" column="downEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
<many-to-one name="building" column="buildingId" not-null="true" class="Building"/>
Modified: shards/trunk/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings-shardedUUID.hbm.xml
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings-shardedUUID.hbm.xml 2007-07-27 12:06:55 UTC (rev 12835)
+++ shards/trunk/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings-shardedUUID.hbm.xml 2007-07-28 03:10:55 UTC (rev 12836)
@@ -108,6 +108,7 @@
<generator class="org.hibernate.shards.id.ShardedUUIDGenerator"/>
</id>
<property name="number" not-null="true"/>
+ <property name="squareFeet" not-null="false"/>
<many-to-one name="goingUp" column="upEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
<many-to-one name="goingDown" column="downEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
<many-to-one name="building" column="buildingId" not-null="true" class="Building"/>
Modified: shards/trunk/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings.hbm.xml
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings.hbm.xml 2007-07-27 12:06:55 UTC (rev 12835)
+++ shards/trunk/src/test/org/hibernate/shards/integration/platform/mysql/config/mappings.hbm.xml 2007-07-28 03:10:55 UTC (rev 12836)
@@ -108,6 +108,7 @@
<generator class="org.hibernate.shards.id.UUIDBigIntGenerator"/>
</id>
<property name="number" not-null="true"/>
+ <property name="squareFeet" not-null="false"/>
<many-to-one name="goingUp" column="upEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
<many-to-one name="goingDown" column="downEscalatorId" unique="true" not-null="false" class="Escalator" cascade="all"/>
<many-to-one name="building" column="buildingId" not-null="true" class="Building"/>
Modified: shards/trunk/src/test/org/hibernate/shards/model/Floor.java
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/model/Floor.java 2007-07-27 12:06:55 UTC (rev 12835)
+++ shards/trunk/src/test/org/hibernate/shards/model/Floor.java 2007-07-28 03:10:55 UTC (rev 12836)
@@ -21,6 +21,7 @@
import org.hibernate.shards.util.Lists;
import java.io.Serializable;
+import java.math.BigDecimal;
import java.util.List;
/**
@@ -30,6 +31,7 @@
private Serializable floorId;
private int number;
+ private BigDecimal squareFeet;
private List<Tenant> tenants;
private List<Office> offices = Lists.newArrayList();
private List<Elevator> elevators = Lists.newArrayList();
@@ -53,6 +55,14 @@
this.number = number;
}
+ public BigDecimal getSquareFeet() {
+ return squareFeet;
+ }
+
+ public void setSquareFeet(BigDecimal squareFeet) {
+ this.squareFeet = squareFeet;
+ }
+
public List<Tenant> getTenants() {
return tenants;
}
Added: shards/trunk/src/test/org/hibernate/shards/strategy/exit/AvgResultsExitOperationTest.java
===================================================================
--- shards/trunk/src/test/org/hibernate/shards/strategy/exit/AvgResultsExitOperationTest.java (rev 0)
+++ shards/trunk/src/test/org/hibernate/shards/strategy/exit/AvgResultsExitOperationTest.java 2007-07-28 03:10:55 UTC (rev 12836)
@@ -0,0 +1,101 @@
+/**
+ * Copyright (C) 2007 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+package org.hibernate.shards.strategy.exit;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Hibernate;
+import org.hibernate.criterion.AvgProjection;
+import org.hibernate.shards.util.Lists;
+import org.hibernate.type.Type;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author maxr(a)google.com (Max Ross)
+ */
+public class AvgResultsExitOperationTest extends TestCase {
+
+ public void testAvgProjectionComesBackAsDouble() {
+ // sharded avg calculation assumes that the avg projection implementation
+ // returns a Double, so let's make sure that assumption is valid
+ AvgProjection ap = new AvgProjection("yam");
+ Type[] types = ap.getTypes(null, null);
+ assertNotNull(types);
+ assertEquals(1, types.length);
+ assertEquals(Hibernate.DOUBLE, types[0]);
+ }
+
+ public void testEmptyList() {
+ AvgResultsExitOperation op = new AvgResultsExitOperation();
+
+ List<Object> result = op.apply(Collections.emptyList());
+ assertEquals(1, result.size());
+ assertNull(result.get(0));
+ }
+
+ public void testSingleResult() {
+ AvgResultsExitOperation op = new AvgResultsExitOperation();
+
+ Object[] objArr = {null, 3};
+ List<Object> result = op.apply(Collections.singletonList((Object) objArr));
+ assertEquals(1, result.size());
+ assertNull(result.get(0));
+
+ objArr[0] = 9.0;
+ result = op.apply(Collections.singletonList((Object) objArr));
+ assertEquals(1, result.size());
+ assertEquals(9.0, result.get(0));
+ }
+
+ public void testMultipleResults() {
+ AvgResultsExitOperation op = new AvgResultsExitOperation();
+
+ Object[] objArr1 = {null, 3};
+ Object[] objArr2 = {2.5, 2};
+ List<Object> result = op.apply(Lists.<Object>newArrayList(objArr1, objArr2));
+ assertEquals(1, result.size());
+ assertEquals(2.5, result.get(0));
+
+ objArr1[0] = 2.0;
+ result = op.apply(Lists.<Object>newArrayList(objArr1, objArr2));
+ assertEquals(1, result.size());
+ assertEquals(2.2, result.get(0));
+ }
+
+ public void testBadInput() {
+ AvgResultsExitOperation op = new AvgResultsExitOperation();
+
+ Object[] objArr = {null};
+ try {
+ op.apply(Collections.singletonList((Object) objArr));
+ fail("expected rte");
+ } catch (IllegalStateException rte) {
+ // good
+ }
+
+ Object obj = new Object();
+ try {
+ op.apply(Collections.singletonList(obj));
+ fail("expected rte");
+ } catch (IllegalStateException rte) {
+ // good
+ }
+ }
+}
17 years, 5 months