Project

General

Profile

Download (6.29 KB) Statistics
| Branch: | Tag: | Revision:
1
// $Id$
2
/**
3
* Copyright (C) 2011 EDIT
4
* European Distributed Institute of Taxonomy
5
* http://www.e-taxonomy.eu
6
*
7
* The contents of this file are subject to the Mozilla Public License Version 1.1
8
* See LICENSE.TXT at the top of this package for the full license terms.
9
*/
10
package eu.etaxonomy.cdm.api.service.search;
11

    
12
import org.apache.log4j.Logger;
13
import org.hibernate.CacheMode;
14
import org.hibernate.FlushMode;
15
import org.hibernate.ScrollMode;
16
import org.hibernate.ScrollableResults;
17
import org.hibernate.Session;
18
import org.hibernate.Transaction;
19
import org.hibernate.search.FullTextSession;
20
import org.hibernate.search.Search;
21
import org.springframework.beans.factory.annotation.Autowired;
22
import org.springframework.orm.hibernate3.HibernateTransactionManager;
23
import org.springframework.stereotype.Component;
24
import org.springframework.transaction.PlatformTransactionManager;
25
import org.springframework.transaction.annotation.Transactional;
26

    
27
import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
28
import eu.etaxonomy.cdm.common.monitor.NullProgressMonitor;
29
import eu.etaxonomy.cdm.common.monitor.RestServiceProgressMonitor;
30
import eu.etaxonomy.cdm.common.monitor.SubProgressMonitor;
31
import eu.etaxonomy.cdm.model.common.CdmBase;
32
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
33
import eu.etaxonomy.cdm.model.taxon.Classification;
34

    
35
/**
36
 * @author Andreas Kohlbecker
37
 * @date Dec 15, 2011
38
 *
39
 */
40
@Component
41
@Transactional
42
public class CdmMassIndexer implements ICdmMassIndexer {
43

    
44
    public static final Logger logger = Logger.getLogger(CdmMassIndexer.class);
45

    
46
    private static final int BATCH_SIZE = 100;
47

    
48
    public HibernateTransactionManager transactionManager;
49

    
50
    @Autowired
51
    public void setTransactionManager(PlatformTransactionManager transactionManager) {
52
        this.transactionManager = (HibernateTransactionManager)transactionManager;
53
    }
54

    
55
    protected Session getSession(){
56
        Session session = transactionManager.getSessionFactory().getCurrentSession();
57
        return session;
58
    }
59

    
60
    protected <T extends CdmBase>void reindex(Class<T> type, IProgressMonitor monitor) {
61

    
62
        FullTextSession fullTextSession = Search.getFullTextSession(getSession());
63

    
64
        fullTextSession.setFlushMode(FlushMode.MANUAL);
65
        fullTextSession.setCacheMode(CacheMode.IGNORE);
66

    
67
        logger.info("start indexing " + type.getName());
68
        monitor.subTask("indexing " + type.getSimpleName());
69
        Transaction transaction = fullTextSession.beginTransaction();
70

    
71
        Long countResult = countEntities(type);
72
        int numOfBatches = calculateNumOfBatches(countResult);
73

    
74
        SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, numOfBatches);
75
        subMonitor.beginTask("Indexing " + type.getSimpleName(), numOfBatches);
76

    
77
        // Scrollable results will avoid loading too many objects in memory
78
        ScrollableResults results = fullTextSession.createCriteria(type).setFetchSize(BATCH_SIZE).scroll(ScrollMode.FORWARD_ONLY);
79
        long index = 0;
80
        int batchesWorked = 0;
81

    
82
        try {
83
            while (results.next()) {
84
                index++;
85
                fullTextSession.index(results.get(0)); // index each element
86
                if (index % BATCH_SIZE == 0 || index == countResult) {
87
                    batchesWorked++;
88
                    fullTextSession.flushToIndexes(); // apply changes to indexes
89
                    fullTextSession.clear(); // clear since the queue is processed
90
                    //                calculateNumOfBatches(index == countResult ? countResult : index);
91
                    logger.info("\tbatch " + batchesWorked + "/" + numOfBatches + " processed");
92
                    subMonitor.internalWorked(1);
93
                    //if(index / BATCH_SIZE > 10 ) break;
94
                }
95
            }
96
        } catch (RuntimeException e) {
97
            //TODO better means to notify that the process has been stopped, using the STOPPED_WORK_INDICATOR is only a hack
98
            monitor.worked(RestServiceProgressMonitor.STOPPED_WORK_INDICATOR);
99
            monitor.done();
100
            throw	e;
101
        }
102
        //transaction.commit(); // no need to commit, transaction will be committed automatically
103
        logger.info("end indexing " + type.getName());
104
        subMonitor.done();
105
    }
106

    
107
    /**
108
     * @param countResult
109
     * @return
110
     */
111
    private int calculateNumOfBatches(Long countResult) {
112
        Long numOfBatches =  countResult > 0 ? ((countResult-1)/BATCH_SIZE)+1 : 0;
113
        return numOfBatches.intValue();
114
    }
115

    
116
    /**
117
     * @param type
118
     * @return
119
     */
120
    private <T> Long countEntities(Class<T> type) {
121
        Object countResultObj = getSession().createQuery("select count(*) from " + type.getName()).uniqueResult();
122
        Long countResult = (Long)countResultObj;
123
        return countResult;
124
    }
125

    
126
    protected <T extends CdmBase>void purge(Class<T> type, IProgressMonitor monitor) {
127

    
128
        FullTextSession fullTextSession = Search.getFullTextSession(getSession());
129

    
130
        logger.info("purging " + type.getName());
131

    
132
        fullTextSession.purgeAll(type);
133
        //transaction.commit(); // no need to commit, transaction will be committed automatically
134
    }
135

    
136
    /* (non-Javadoc)
137
     * @see eu.etaxonomy.cdm.database.IMassIndexer#reindex()
138
     */
139
    @Override
140
    public void reindex(IProgressMonitor monitor){
141

    
142
        if(monitor == null){
143
            monitor = new NullProgressMonitor();
144
        }
145

    
146
        monitor.setTaskName("CdmMassIndexer");
147
        // retrieve total count of batches
148
        int totalNumOfBatches = 0;
149
        for(Class type : indexedClasses()){
150
            totalNumOfBatches += calculateNumOfBatches(countEntities(type));
151
        }
152
        monitor.beginTask("Reindexing " + indexedClasses().length + " classes", totalNumOfBatches);
153
        for(Class type : indexedClasses()){
154
            reindex(type, monitor);
155
        }
156
        monitor.done();
157
    }
158

    
159
    /* (non-Javadoc)
160
     * @see eu.etaxonomy.cdm.database.IMassIndexer#purge()
161
     */
162
    @Override
163
    public void purge(IProgressMonitor monitor){
164

    
165
        for(Class type : indexedClasses()){
166
            purge(type, monitor);
167
        }
168
    }
169

    
170
    /**
171
     * @return
172
     */
173
    public Class[] indexedClasses() {
174
        return new Class[] {
175
                DescriptionElementBase.class,
176
                Classification.class,
177
//                TaxonBase.class
178
                };
179
    }
180
}
(1-1/7)