lucene etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
lucene etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

16 Haziran 2015 Salı

Lucene tip

If you manually delete some files from the lucene index directory, than the next time you try to index you will get an error about the location being OUT-OF-SYNC. The error message may look like something like that:
 Entity com.mypackage.MyEntity Id 12345 Work Type org.hibernate.search.backend.UpdateLuceneWork  
 Entity com.mypackage.MyEntity Id 12346 Work Type org.hibernate.search.backend.UpdateLuceneWork  
 : org.apache.lucene.store.LockObtainFailedException: Lock obtain timed out: NativeFSLock@/path/to/index/com.mypackage.MyEntity/write.lock  
 at org.apache.lucene.store.Lock.obtain(Lock.java:84) [lucene-core-3.5.0.jar:3.5.0 1204425 - simon - 2011-11-21 11:20:12]  
 at org.apache.lucene.index.IndexWriter.(IndexWriter.java:1108) [lucene-core-3.5.0.jar:3.5.0 1204425 - simon - 2011-11-21 11:20:12]  
 at org.hibernate.search.backend.impl.lucene.IndexWriterHolder.createNewIndexWriter(IndexWriterHolder.java:127) [hibernate-search-engine-4.1.0.Final.jar:4.1.0.Final]  
 at org.hibernate.search.backend.impl.lucene.IndexWriterHolder.getIndexWriter(IndexWriterHolder.java:102) [hibernate-search-engine-4.1.0.Final.jar:4.1.0.Final]  
 at org.hibernate.search.backend.impl.lucene.AbstractWorkspaceImpl.getIndexWriter(AbstractWorkspaceImpl.java:119) [hibernate-search-engine-4.1.0.Final.jar:4.1.0.Final]  
 at org.hibernate.search.backend.impl.lucene.LuceneBackendQueueTask.applyUpdates(LuceneBackendQueueTask.java:99) [hibernate-search-engine-4.1.0.Final.jar:4.1.0.Final]  
 at org.hibernate.search.backend.impl.lucene.LuceneBackendQueueTask.run(LuceneBackendQueueTask.java:67) [hibernate-search-engine-4.1.0.Final.jar:4.1.0.Final]  
 at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) [rt.jar:1.7.0_03]  
 at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) [rt.jar:1.7.0_03]  
 at java.util.concurrent.FutureTask.run(FutureTask.java:166) [rt.jar:1.7.0_03]  
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) [rt.jar:1.7.0_03]  
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) [rt.jar:1.7.0_03]  
 at java.lang.Thread.run(Thread.java:722) [rt.jar:1.7.0_03]  


My solution to this situation, is clearing the OUT-OF-SYNC folder content, restart the server and reindex.
More practical solutions may exist, but that worked for me.. By the way, just deleting the write.lock file does not work here..
Another tip about the lock mechanism:
(from http://www.gossamer-threads.com/lists/lucene/java-user/261725 :)

The existence of the write.lock file has nothing to do with actual locking. The lock file is just a placeholder file (0 bytes) on which the lock during indexing is applied (the actual locking is done on this file using a fnctl). When indexing finishes, the lock is removed from this file, but the file stays alive. This was different in Lucene 3, where the lock was also removed. But this caused problems because of non-atomic file operations. Lock factory only checks the "lock on the file", not "the existence of the file as a lock". 

17 Mart 2015 Salı

Lucene on clustered environment

I have a task to refresh lucene indexes periodically. However, when the application is deployed on a clustered environment, each node tries to start indexing process and others display the following error:

 Entity com.me.MyEntity Id 1783 Work Type org.hibernate.search.backend.UpdateLuceneWork  
 : org.apache.lucene.store.LockObtainFailedException: Lock obtain timed out: NativeFSLock@/path_to_index/com.me.MyEntity/write.lock  
 at org.apache.lucene.store.Lock.obtain(Lock.java:84) [lucene-core-3.5.0.jar:3.5.0 1204425 - simon - 2011-11-21 11:20:12]  
 at org.apache.lucene.index.IndexWriter.<init>(IndexWriter.java:1108) [lucene-core-3.5.0.jar:3.5.0 1204425 - simon - 2011-11-21 11:20:12]  
 at org.hibernate.search.backend.impl.lucene.IndexWriterHolder.createNewIndexWriter(IndexWriterHolder.java:127) [hibernate-search-engine-4.1.0.Final.jar:4.1.0.Final]  
 at org.hibernate.search.backend.impl.lucene.IndexWriterHolder.getIndexWriter(IndexWriterHolder.java:102) [hibernate-search-engine-4.1.0.Final.jar:4.1.0.Final]  
 at org.hibernate.search.backend.impl.lucene.AbstractWorkspaceImpl.getIndexWriter(AbstractWorkspaceImpl.java:119) [hibernate-search-engine-4.1.0.Final.jar:4.1.0.Final]  
 at org.hibernate.search.backend.impl.lucene.LuceneBackendQueueTask.applyUpdates(LuceneBackendQueueTask.java:99) [hibernate-search-engine-4.1.0.Final.jar:4.1.0.Final]  
 at org.hibernate.search.backend.impl.lucene.LuceneBackendQueueTask.run(LuceneBackendQueueTask.java:67) [hibernate-search-engine-4.1.0.Final.jar:4.1.0.Final]  
 at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) [rt.jar:1.7.0_03]  
 at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) [rt.jar:1.7.0_03]  
 at java.util.concurrent.FutureTask.run(FutureTask.java:166) [rt.jar:1.7.0_03]  
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) [rt.jar:1.7.0_03]  
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) [rt.jar:1.7.0_03]  
 at java.lang.Thread.run(Thread.java:722) [rt.jar:1.7.0_03]  

Those links may help you:
http://stackoverflow.com/questions/1228833/sharing-a-java-synchronized-block-across-a-cluster-or-using-a-global-lock 
http://stackoverflow.com/questions/17921898/using-lucene-in-a-clustered-environment-with-shared-nfs
http://forums.terracotta.org/forums/posts/list/6707.page
http://stackoverflow.com/questions/13486426/how-to-unlock-the-index-directory-in-lucene

But, i solved my case by adding a random timer to sleep :
 @Schedule(...)   
      public void myTask() {  
           try {  
                long sleepFor = (long)(Math.random() * 100000);  
                Thread.sleep(sleepFor); // hope nodes sleep different amount of time  
                log.infov("Sleep for this cluster : " + sleepFor);  
                Directory directory = FSDirectory.open(new File("path_to_index/com.me.MyEntity/"));  
             if (directory.fileExists("write.lock")) {  
               log.infov("ATTENTION!!! Already done by the other node!!");  
               return;  
             }  
             directory.close();  
 ...  

The random timer weakens the syncronization between nodes and the one who sleeps the least does the job! Then others know about this by checking the lock file..

Hope this helps..

9 Mart 2015 Pazartesi

lucene date issue

When indexing with Lucene (Hibernate Search), you may notice difference between dates in the database and indexed values. For example, in my case, Lucene dates were a day before the dates in the database. This is due to timezone differences. In the following annotation, org.hibernate.search.annotations.DateBridge assumes GMT time..
 @Column(name = "CREATED")  
 @Temporal(TemporalType.TIMESTAMP)  
 @DateBridge(resolution = Resolution.DAY)  
 private Date created;  
My solution was to write a custom field bridge named ESTDateBridge by copying the original DateBridge code and changing the default timezone from GMT to "America/New_York" (writing EST did not work..)
The working annotation is as follows:

 @Column(name = "CREATED")  
 @Temporal(TemporalType.TIMESTAMP)  
 @FieldBridge(impl = ESTDateBridge.class)  
 private Date created;  

Some references:
http://jamesjefferies.com/2009/04/22/hibernate-search-lucene-and-greenwich-mean-time/ 
https://access.redhat.com/documentation/en-US/Red_Hat_JBoss_Data_Grid/6.4/html/Infinispan_Query_Guide/sect-Bridges.html 
https://forum.hibernate.org/viewtopic.php?f=9&t=990266&view=next 

27 Kasım 2014 Perşembe

a lucene tip

Retrieving large resultsets with lucene may degrade performance as in here: http://stackoverflow.com/questions/9868419/how-to-get-total-count-in-hibernate-full-text-search 
You can choose to show the first top k results, or you can paginate lucene as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// can get the resultsize easily, so you know how many pages would be..
Integer resultSize = jpaQuery.getResultSize(); 
// I use 1000 as max results, but it depends.. just try to find the optimum.
Integer pageCount = resultSize / MAX_RESULTS + 1;
List<Object[]> rawQueryResultList = new ArrayList<>();
for(int page = 0; page < pageCount; page++) {  
 jpaQuery.setFirstResult(page * MAX_RESULTS);
 jpaQuery.setMaxResults(MAX_RESULTS);
  
 rawQueryResultList.addAll(jpaQuery.getResultList());
}