Skip to content

Commit

Permalink
HSEARCH-1427 Create a base template to help implementors of ShardIden…
Browse files Browse the repository at this point in the history
…tifierProvider (rebased from Sanne's work)
  • Loading branch information
gunnarmorling committed Oct 7, 2013
1 parent 2703f3a commit 6838d26
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 40 deletions.
@@ -0,0 +1,76 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.search.store;

import java.util.Collections;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;

import org.hibernate.search.filter.FullTextFilterImplementor;
import org.hibernate.search.spi.BuildContext;

/**
* Suggested parent class to create custom ShardIdentifierProvider implementations.
*
* The implementation must have a no-arg constructor.
*
* @author Sanne Grinovero
*/
public abstract class ShardIdentifierProviderTemplate implements ShardIdentifierProvider {

private volatile Set<String> knownShards = Collections.emptySet();

@Override
public final void initialize(Properties properties, BuildContext buildContext) {
Set<String> initialShardNames = loadInitialShardNames( properties, buildContext );
knownShards = Collections.unmodifiableSet( new HashSet<String>( initialShardNames ) );
}

protected abstract Set<String> loadInitialShardNames(Properties properties, BuildContext buildContext);

protected final void addShard(final String shardName) {
if ( ! knownShards.contains( shardName ) ) {
addShardSynchronized( shardName );
}
}

private synchronized void addShardSynchronized(final String shardName) {
HashSet<String> newCopy = new HashSet<String>( knownShards );
newCopy.add( shardName );
knownShards = Collections.unmodifiableSet( newCopy );
}

@Override
public final Set<String> getAllShardIdentifiers() {
return knownShards;
}

/**
* Potentially suited to be overridden if you are able to narrow doen the shard
* selection based on the active FullTextFilters.
*/
@Override
public Set<String> getShardIdentifiersForQuery(FullTextFilterImplementor[] fullTextFilters) {
return getAllShardIdentifiers();
}

}
Expand Up @@ -20,10 +20,12 @@
*/
package org.hibernate.search.test.shards;

import static org.fest.assertions.Assertions.assertThat;
import static org.junit.Assert.assertEquals;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
Expand All @@ -33,12 +35,10 @@
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.store.FSDirectory;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Property;
Expand All @@ -47,18 +47,15 @@
import org.hibernate.search.engine.ServiceManager;
import org.hibernate.search.engine.spi.EntityIndexBinding;
import org.hibernate.search.engine.spi.SearchFactoryImplementor;
import org.hibernate.search.filter.FullTextFilterImplementor;
import org.hibernate.search.hcore.impl.HibernateSessionFactoryServiceProvider;
import org.hibernate.search.spi.BuildContext;
import org.hibernate.search.store.ShardIdentifierProvider;
import org.hibernate.search.store.ShardIdentifierProviderTemplate;
import org.hibernate.search.test.SearchTestCaseJUnit4;
import org.hibernate.search.test.TestConstants;
import org.junit.Before;
import org.junit.Test;

import static org.fest.assertions.Assertions.assertThat;
import static org.junit.Assert.assertEquals;

/**
* @author Emmanuel Bernard <emmanuel@hibernate.org>
*/
Expand All @@ -68,6 +65,7 @@ public class DynamicShardingTest extends SearchTestCaseJUnit4 {
private Animal spider;
private Animal bear;

@Override
@Before
public void setUp() throws Exception {
super.setUp();
Expand Down Expand Up @@ -207,12 +205,20 @@ private SearchFactoryImplementor getIndependentNewSearchFactory() {
return (SearchFactoryImplementor) fullTextSession.getSearchFactory();
}

public static class AnimalShardIdentifierProvider implements ShardIdentifierProvider {
public static class AnimalShardIdentifierProvider extends ShardIdentifierProviderTemplate implements ShardIdentifierProvider {

private volatile Set<String> knownShards = Collections.emptySet();
@Override
public String getShardIdentifier(Class<?> entityType, Serializable id, String idAsString, Document document) {
if ( entityType.equals( Animal.class ) ) {
String type = document.getFieldable( "type" ).stringValue();
addShard( type );
return type;
}
throw new RuntimeException( "Animal expected but found " + entityType );
}

@Override
public void initialize(Properties properties, BuildContext buildContext) {
protected Set<String> loadInitialShardNames(Properties properties, BuildContext buildContext) {
ServiceManager serviceManager = buildContext.getServiceManager();
SessionFactory sessionFactory = serviceManager.requestService( HibernateSessionFactoryServiceProvider.class, buildContext );
Session session = sessionFactory.openSession();
Expand All @@ -221,40 +227,12 @@ public void initialize(Properties properties, BuildContext buildContext) {
initialShardsCriteria.setProjection( Projections.distinct( Property.forName( "type" ) ) );

@SuppressWarnings("unchecked")
List<String> initialTypes = (List<String>) initialShardsCriteria.list();
knownShards = Collections.unmodifiableSet( new HashSet<String>( initialTypes ) );
List<String> initialTypes = initialShardsCriteria.list();
return new HashSet<String>( initialTypes );
}
finally {
session.close();
}
}

private synchronized void addShard(String shardNames) {
HashSet<String> newCopy = new HashSet<String>( knownShards );
newCopy.add( shardNames );
knownShards = Collections.unmodifiableSet( newCopy );
}

@Override
public String getShardIdentifier(Class<?> entityType, Serializable id, String idAsString, Document document) {
if ( entityType.equals( Animal.class ) ) {
String type = document.getFieldable( "type" ).stringValue();
if ( ! knownShards.contains( type ) ) {
addShard( type );
}
return type;
}
throw new RuntimeException( "Animal expected but found " + entityType );
}

@Override
public Set<String> getShardIdentifiersForQuery(FullTextFilterImplementor[] fullTextFilters) {
return getAllShardIdentifiers();
}

@Override
public Set<String> getAllShardIdentifiers() {
return knownShards;
}
}
}

0 comments on commit 6838d26

Please sign in to comment.