• Views
  • Iteration Report
  • My Iteration Report
  •  
OMERO.server
  • Login
  • Help/Guide
  • About Trac
  • Preferences
  • Wiki
  • Timeline
  • Roadmap
  • Browse Source
  • View Tickets
  • Search

Context Navigation

  • Last Change
  • Annotate
  • Revision Log

root/trunk/components/server/src/ome/logic/UpdateImpl.java

Revision 2495, 10.8 kB (checked in by jmoore, 7 months ago)

OmeroSearch : Adding repetitions per indexing for reducing backlog

Under certain situations (like the creation of a fresh index), one
indexing every 30 seconds can lead to extreme wait times ( > week ).
Therefore, in addition to the omero.search.batch setting which
allows larger clumps, it is now possible to repeat indexing
multiple times if the backlog is sufficiently large (relative
to batch size, but not currently relative to indexing frequency.)

  • Added omero.search.repetitions property
  • Changd method signature of EventLogLoader.more()
  • Added FullTextIndexer.doMore() which suggests a repetition
  • Property svn:keywords set to
    Date
    Revision
    Id
    URL
Line 
1/*
2 * ome.logic.UpdateImpl
3 *
4 *   Copyright 2006 University of Dundee. All rights reserved.
5 *   Use is subject to license terms supplied in LICENSE.txt
6 */
7
8/*------------------------------------------------------------------------------
9 *
10 * Written by:    Josh Moore <josh.moore@gmx.de>
11 *
12 *------------------------------------------------------------------------------
13 */
14
15package ome.logic;
16
17// Java imports
18import java.sql.SQLException;
19import java.util.Collection;
20
21import javax.annotation.security.RolesAllowed;
22import javax.ejb.Local;
23import javax.ejb.Remote;
24import javax.ejb.Stateless;
25import javax.ejb.TransactionManagement;
26import javax.ejb.TransactionManagementType;
27import javax.interceptor.Interceptors;
28
29import ome.api.IUpdate;
30import ome.api.ServiceInterface;
31import ome.api.local.LocalQuery;
32import ome.api.local.LocalUpdate;
33import ome.conditions.ApiUsageException;
34import ome.conditions.ValidationException;
35import ome.model.IObject;
36import ome.model.meta.EventLog;
37import ome.parameters.Parameters;
38import ome.services.fulltext.EventLogLoader;
39import ome.services.fulltext.FullTextBridge;
40import ome.services.fulltext.FullTextIndexer;
41import ome.services.fulltext.FullTextThread;
42import ome.services.sessions.SessionManager;
43import ome.services.util.Executor;
44import ome.services.util.OmeroAroundInvoke;
45import ome.tools.hibernate.UpdateFilter;
46import ome.util.Utils;
47
48import org.hibernate.HibernateException;
49import org.hibernate.Session;
50import org.jboss.annotation.ejb.LocalBinding;
51import org.jboss.annotation.ejb.RemoteBinding;
52import org.jboss.annotation.ejb.RemoteBindings;
53import org.springframework.orm.hibernate3.HibernateCallback;
54import org.springframework.transaction.annotation.Transactional;
55
56/**
57 * implementation of the IUpdate service interface
58 *
59 * @author Josh Moore, <a href="mailto:josh.moore@gmx.de">josh.moore@gmx.de</a>
60 * @version 1.0 <small> (<b>Internal version:</b> $Rev$ $Date$) </small>
61 * @since OMERO 3.0
62 */
63@TransactionManagement(TransactionManagementType.BEAN)
64@Transactional(readOnly = false)
65@Stateless
66@Remote(IUpdate.class)
67@RemoteBindings( {
68        @RemoteBinding(jndiBinding = "omero/remote/ome.api.IUpdate"),
69        @RemoteBinding(jndiBinding = "omero/secure/ome.api.IUpdate", clientBindUrl = "sslsocket://0.0.0.0:3843") })
70@Local(LocalUpdate.class)
71@LocalBinding(jndiBinding = "omero/local/ome.api.local.LocalUpdate")
72@Interceptors( { OmeroAroundInvoke.class, SimpleLifecycle.class })
73public class UpdateImpl extends AbstractLevel1Service implements LocalUpdate {
74
75    protected transient LocalQuery localQuery;
76
77    protected transient Executor executor;
78
79    protected transient SessionManager sessionManager;
80
81    protected transient FullTextBridge fullTextBridge;
82
83    public final void setQueryService(LocalQuery query) {
84        getBeanHelper().throwIfAlreadySet(this.localQuery, query);
85        this.localQuery = query;
86    }
87
88    public void setExecutor(Executor executor) {
89        getBeanHelper().throwIfAlreadySet(this.executor, executor);
90        this.executor = executor;
91    }
92
93    public void setSessionManager(SessionManager sessionManager) {
94        getBeanHelper().throwIfAlreadySet(this.sessionManager, sessionManager);
95        this.sessionManager = sessionManager;
96    }
97
98    public void setFullTextBridge(FullTextBridge fullTextBridge) {
99        getBeanHelper().throwIfAlreadySet(this.fullTextBridge, fullTextBridge);
100        this.fullTextBridge = fullTextBridge;
101    }
102
103    public Class<? extends ServiceInterface> getServiceInterface() {
104        return IUpdate.class;
105    };
106
107    // ~ LOCAL PUBLIC METHODS
108    // =========================================================================
109
110    @RolesAllowed("user")
111    public void rollback() {
112        getHibernateTemplate().execute(new HibernateCallback() {
113            public Object doInHibernate(Session session)
114                    throws HibernateException, SQLException {
115                session.connection().rollback();
116                return null;
117            };
118        });
119    }
120
121    @RolesAllowed("user")
122    public void flush() {
123        getHibernateTemplate().execute(new HibernateCallback() {
124            public Object doInHibernate(Session session)
125                    throws HibernateException, SQLException {
126                session.flush();
127                return null;
128            };
129        });
130    }
131
132    @RolesAllowed("user")
133    public void commit() {
134        getHibernateTemplate().execute(new HibernateCallback() {
135            public Object doInHibernate(Session session)
136                    throws HibernateException, SQLException {
137                session.connection().commit();
138                return null;
139            };
140        });
141    }
142
143    // ~ INTERFACE METHODS
144    // =========================================================================
145
146    @RolesAllowed("user")
147    public void saveObject(IObject graph) {
148        doAction(graph, new UpdateAction<IObject>() {
149            @Override
150            public IObject run(IObject value, UpdateFilter filter) {
151                return internalSave(value, filter);
152            }
153        });
154    }
155
156    @RolesAllowed("user")
157    public IObject saveAndReturnObject(IObject graph) {
158        return doAction(graph, new UpdateAction<IObject>() {
159            @Override
160            public IObject run(IObject value, UpdateFilter filter) {
161                return internalSave(value, filter);
162            }
163        });
164    }
165
166    @RolesAllowed("user")
167    public void saveCollection(Collection graph) {
168        doAction(graph, new UpdateAction<Collection>() {
169            @Override
170            public Collection run(Collection value, UpdateFilter filter) {
171                for (Object o : value) {
172                    IObject obj = (IObject) o;
173                    obj = internalSave(obj, filter);
174                }
175                return null;
176            }
177        });
178    }
179
180    @RolesAllowed("user")
181    public IObject[] saveAndReturnArray(IObject[] graph) {
182        return doAction(graph, new UpdateAction<IObject[]>() {
183            @Override
184            public IObject[] run(IObject[] value, UpdateFilter filter) {
185                IObject[] copy = new IObject[value.length];
186                for (int i = 0; i < value.length; i++) {
187                    copy[i] = internalSave(value[i], filter);
188                }
189                return copy;
190            }
191        });
192    }
193
194    @RolesAllowed("user")
195    public void saveArray(IObject[] graph) {
196        doAction(graph, new UpdateAction<IObject[]>() {
197            @Override
198            public IObject[] run(IObject[] value, UpdateFilter filter) {
199                IObject[] copy = new IObject[value.length];
200                for (int i = 0; i < value.length; i++) {
201                    copy[i] = internalSave(value[i], filter);
202                }
203                return copy;
204            }
205        });
206    }
207
208    @RolesAllowed("user")
209    public void deleteObject(IObject row) {
210        if (row == null) {
211            return;
212        }
213        if (row.getId() == null) {
214            throw new ApiUsageException(
215                    "Non-managed IObject entity cannot be deleted. Must have an id.");
216        }
217        doAction(row, new UpdateAction<IObject>() {
218            @Override
219            public IObject run(IObject value, UpdateFilter filter) {
220                internalDelete(value, filter);
221                return null;
222            }
223        });
224    }
225
226    @RolesAllowed("system")
227    public void indexObject(IObject row) {
228        if (row == null || row.getId() == null) {
229            throw new ValidationException(
230                    "Non-managed object canoot be indexed.");
231        }
232
233        CreationLogLoader logs = new CreationLogLoader(localQuery, row);
234        FullTextIndexer fti = new FullTextIndexer(logs);
235        FullTextThread ftt = new FullTextThread(sessionManager, executor, fti,
236                this.fullTextBridge, true);
237        ftt.run();
238    }
239
240    // ~ Internals
241    // =========================================================
242    private void beforeUpdate(Object argument, UpdateFilter filter) {
243
244        if (argument == null) {
245            throw new IllegalArgumentException(
246                    "Argument to save cannot be null.");
247        }
248
249        if (getBeanHelper().getLogger().isDebugEnabled()) {
250            getBeanHelper().getLogger().debug(" Saving event before merge. ");
251        }
252
253    }
254
255    /**
256     * Note if we use anything other than merge here, functionality from
257     * {@link ome.tools.hibernate.MergeEventListener} needs to be moved to
258     * {@link UpdateFilter} or to another event listener.
259     */
260    protected IObject internalSave(IObject obj, UpdateFilter filter) {
261        if (getBeanHelper().getLogger().isDebugEnabled()) {
262            getBeanHelper().getLogger().debug(" Internal save. ");
263        }
264
265        IObject result = (IObject) filter.filter(null, obj);
266        result = (IObject) getHibernateTemplate().merge(result);
267        return result;
268    }
269
270    protected void internalDelete(IObject obj, UpdateFilter filter) {
271        if (getBeanHelper().getLogger().isDebugEnabled()) {
272            getBeanHelper().getLogger().debug(" Internal delete. ");
273        }
274
275        getHibernateTemplate().delete(
276                getHibernateTemplate().load(Utils.trueClass(obj.getClass()),
277                        obj.getId()));
278    }
279
280    private void afterUpdate(UpdateFilter filter) {
281
282        if (getBeanHelper().getLogger().isDebugEnabled()) {
283            getBeanHelper().getLogger().debug(" Post-save cleanup. ");
284        }
285
286        // Clean up
287        getHibernateTemplate().flush();
288        filter.unloadReplacedObjects();
289
290    }
291
292    private <T> T doAction(T graph, UpdateAction<T> action) {
293        T retVal;
294        UpdateFilter filter = new UpdateFilter();
295        try {
296            beforeUpdate(graph, filter);
297            retVal = action.run(graph, filter);
298            afterUpdate(filter);
299        } finally {
300            // currently nothing.
301        }
302        return retVal;
303    }
304
305    private abstract class UpdateAction<T> {
306        public abstract T run(T value, UpdateFilter filter);
307    }
308
309}
310
311/**
312 * {@link EventLogLoader} which loads a single instance.
313 */
314class CreationLogLoader extends EventLogLoader {
315
316    final private LocalQuery query;
317
318    private IObject obj;
319
320    public CreationLogLoader(LocalQuery query, IObject obj) {
321        this.query = query;
322        this.obj = obj;
323    }
324
325    @Override
326    public EventLog query() {
327        if (obj == null) {
328            return null;
329        } else {
330            EventLog el = query.findByQuery("select el from EventLog el "
331                    + "where el.action = 'INSERT' and "
332                    + "el.entityType = :type and " + "el.entityId = :id",
333                    new Parameters()
334                            .addString("type", obj.getClass().getName()).addId(
335                                    obj.getId()));
336            obj = null;
337            return el;
338        }
339    }
340
341    @Override
342    public long more() {
343        return 0;
344    }
345
346}
Note: See TracBrowser for help on using the browser.

Download in other formats:

  • Plain Text
  • Original Format

Trac Powered

Powered by Trac 0.11
By Edgewall Software.

Visit the Trac open source project at
http://trac.edgewall.org/