KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > engine > ActionQueue


1 // $Id: ActionQueue.java,v 1.8 2005/07/20 07:16:17 oneovthafew Exp $
2
package org.hibernate.engine;
3
4 import org.hibernate.action.EntityInsertAction;
5 import org.hibernate.action.EntityDeleteAction;
6 import org.hibernate.action.Executable;
7 import org.hibernate.action.EntityUpdateAction;
8 import org.hibernate.action.CollectionRecreateAction;
9 import org.hibernate.action.CollectionRemoveAction;
10 import org.hibernate.action.CollectionUpdateAction;
11 import org.hibernate.action.EntityIdentityInsertAction;
12 import org.hibernate.action.BulkOperationCleanupAction;
13 import org.hibernate.HibernateException;
14 import org.hibernate.AssertionFailure;
15 import org.hibernate.cache.CacheException;
16 import org.apache.commons.logging.Log;
17 import org.apache.commons.logging.LogFactory;
18
19 import java.util.ArrayList JavaDoc;
20 import java.util.List JavaDoc;
21 import java.util.Set JavaDoc;
22 import java.io.ObjectInputStream JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.Serializable JavaDoc;
25
26 /**
27  * Responsible for maintaing the queue of actions related to events.
28  * </p>
29  * The ActionQueue holds the DML operations queued as part of a session's
30  * transactional-write-behind semantics. DML operations are queued here
31  * until a flush forces them to be executed against the database.
32  *
33  * @author <a HREF="mailto:steve@hibernate.org">Steve Ebersole</a>
34  */

35 public class ActionQueue implements Serializable JavaDoc {
36
37     private static final Log log = LogFactory.getLog( ActionQueue.class );
38     private static final int INIT_QUEUE_LIST_SIZE = 5;
39
40     private SessionImplementor session;
41
42     // Object insertions, updates, and deletions have list semantics because
43
// they must happen in the right order so as to respect referential
44
// integrity
45
private ArrayList JavaDoc insertions;
46     private ArrayList JavaDoc deletions;
47     private ArrayList JavaDoc updates;
48     // Actually the semantics of the next three are really "Bag"
49
// Note that, unlike objects, collection insertions, updates,
50
// deletions are not really remembered between flushes. We
51
// just re-use the same Lists for convenience.
52
private ArrayList JavaDoc collectionCreations;
53     private ArrayList JavaDoc collectionUpdates;
54     private ArrayList JavaDoc collectionRemovals;
55
56     private transient ArrayList JavaDoc executions;
57
58     /**
59      * Constructs an action queue bound to the given session.
60      *
61      * @param session The session "owning" this queue.
62      */

63     public ActionQueue(SessionImplementor session) {
64         this.session = session;
65
66         insertions = new ArrayList JavaDoc( INIT_QUEUE_LIST_SIZE );
67         deletions = new ArrayList JavaDoc( INIT_QUEUE_LIST_SIZE );
68         updates = new ArrayList JavaDoc( INIT_QUEUE_LIST_SIZE );
69
70         collectionCreations = new ArrayList JavaDoc( INIT_QUEUE_LIST_SIZE );
71         collectionRemovals = new ArrayList JavaDoc( INIT_QUEUE_LIST_SIZE );
72         collectionUpdates = new ArrayList JavaDoc( INIT_QUEUE_LIST_SIZE );
73
74         executions = new ArrayList JavaDoc( INIT_QUEUE_LIST_SIZE * 3 );
75     }
76
77     private void readObject(ObjectInputStream JavaDoc ois) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
78         ois.defaultReadObject();
79         executions = new ArrayList JavaDoc( INIT_QUEUE_LIST_SIZE * 3 );
80     }
81
82     public void clear() {
83         updates.clear();
84         insertions.clear();
85         deletions.clear();
86
87         collectionCreations.clear();
88         collectionRemovals.clear();
89         collectionUpdates.clear();
90     }
91
92     public void addAction(EntityInsertAction action) {
93         insertions.add( action );
94     }
95
96     public void addAction(EntityDeleteAction action) {
97         deletions.add( action );
98     }
99
100     public void addAction(EntityUpdateAction action) {
101         updates.add( action );
102     }
103
104     public void addAction(CollectionRecreateAction action) {
105         collectionCreations.add( action );
106     }
107
108     public void addAction(CollectionRemoveAction action) {
109         collectionRemovals.add( action );
110     }
111
112     public void addAction(CollectionUpdateAction action) {
113         collectionUpdates.add( action );
114     }
115
116     public void addAction(EntityIdentityInsertAction insert) {
117         insertions.add( insert );
118     }
119
120     public void addAction(BulkOperationCleanupAction cleanupAction) {
121         // Add these directly to the executions queue
122
executions.add( cleanupAction );
123     }
124
125     /**
126      * Perform all currently queued entity-insertion actions.
127      *
128      * @throws HibernateException error executing queued insertion actions.
129      */

130     public void executeInserts() throws HibernateException {
131         executeActions( insertions );
132     }
133
134     /**
135      * Perform all currently queued actions.
136      *
137      * @throws HibernateException error executing queued actions.
138      */

139     public void executeActions() throws HibernateException {
140         executeActions( insertions );
141         executeActions( updates );
142         executeActions( collectionRemovals );
143         executeActions( collectionUpdates );
144         executeActions( collectionCreations );
145         executeActions( deletions );
146     }
147
148     /**
149      * Prepares the internal action queues for execution.
150      *
151      * @throws HibernateException error preparing actions.
152      */

153     public void prepareActions() throws HibernateException {
154         prepareActions( collectionRemovals );
155         prepareActions( collectionUpdates );
156         prepareActions( collectionCreations );
157     }
158
159     /**
160      * Performs cleanup of any held cache softlocks.
161      *
162      * @param success Was the transaction successful.
163      */

164     public void afterTransactionCompletion(boolean success) {
165         int size = executions.size();
166         final boolean invalidateQueryCache = session.getFactory().getSettings().isQueryCacheEnabled();
167         for ( int i = 0; i < size; i++ ) {
168             try {
169                 Executable exec = ( Executable ) executions.get(i);
170                 try {
171                     exec.afterTransactionCompletion( success );
172                 }
173                 finally {
174                     if ( invalidateQueryCache ) {
175                         session.getFactory().getUpdateTimestampsCache().invalidate( exec.getPropertySpaces() );
176                     }
177                 }
178             }
179             catch (CacheException ce) {
180                 log.error( "could not release a cache lock", ce );
181                 // continue loop
182
}
183             catch (Exception JavaDoc e) {
184                 throw new AssertionFailure( "Exception releasing cache locks", e );
185             }
186         }
187         executions.clear();
188     }
189
190     /**
191      * Check whether the given tables/query-spaces are to be executed against
192      * given the currently queued actions.
193      *
194      * @param tables The table/query-spaces to check.
195      * @return
196      */

197     public boolean areTablesToBeUpdated(Set JavaDoc tables) {
198         return areTablesToUpdated( updates, tables ) ||
199                 areTablesToUpdated( insertions, tables ) ||
200                 areTablesToUpdated( deletions, tables ) ||
201                 areTablesToUpdated( collectionUpdates, tables ) ||
202                 areTablesToUpdated( collectionCreations, tables ) ||
203                 areTablesToUpdated( collectionRemovals, tables );
204     }
205
206     public boolean areInsertionsOrDeletionsQueued() {
207         return ( insertions.size() > 0 || deletions.size() > 0 );
208     }
209
210     private static boolean areTablesToUpdated(List JavaDoc executables, Set JavaDoc set) {
211         int size = executables.size();
212         for ( int j = 0; j < size; j++ ) {
213             Serializable JavaDoc[] spaces = ( (Executable) executables.get(j) ).getPropertySpaces();
214             for ( int i = 0; i < spaces.length; i++ ) {
215                 if ( set.contains( spaces[i] ) ) {
216                     if ( log.isDebugEnabled() ) log.debug( "changes must be flushed to space: " + spaces[i] );
217                     return true;
218                 }
219             }
220         }
221         return false;
222     }
223
224     private void executeActions(List JavaDoc list) throws HibernateException {
225         int size = list.size();
226         for ( int i = 0; i < size; i++ ) {
227             execute( (Executable) list.get(i) );
228         }
229         list.clear();
230         session.getBatcher().executeBatch();
231     }
232     
233     public void execute(Executable executable) {
234         final boolean lockQueryCache = session.getFactory().getSettings().isQueryCacheEnabled();
235         if ( executable.hasAfterTransactionCompletion() || lockQueryCache ) {
236             executions.add( executable );
237         }
238         if (lockQueryCache) {
239             session.getFactory()
240                 .getUpdateTimestampsCache()
241                 .preinvalidate( executable.getPropertySpaces() );
242         }
243         executable.execute();
244     }
245
246     private void prepareActions(List JavaDoc queue) throws HibernateException {
247         int size = queue.size();
248         for ( int i=0; i<size; i++ ) {
249             Executable executable = ( Executable ) queue.get(i);
250             executable.beforeExecutions();
251         }
252     }
253
254     /**
255      * Returns a string representation of the object.
256      *
257      * @return a string representation of the object.
258      */

259     public String JavaDoc toString() {
260         return new StringBuffer JavaDoc()
261                 .append("ActionQueue[insertions=").append(insertions)
262                 .append(" updates=").append(updates)
263                 .append(" deletions=").append(deletions)
264                 .append(" collectionCreations=").append(collectionCreations)
265                 .append(" collectionRemovals=").append(collectionRemovals)
266                 .append(" collectionUpdates=").append(collectionUpdates)
267                 .append("]")
268                 .toString();
269     }
270
271     public int numberOfCollectionRemovals() {
272         return collectionRemovals.size();
273     }
274
275     public int numberOfCollectionUpdates() {
276         return collectionUpdates.size();
277     }
278
279     public int numberOfCollectionCreations() {
280         return collectionCreations.size();
281     }
282
283     public int numberOfDeletions() {
284         return deletions.size();
285     }
286
287     public int numberOfUpdates() {
288         return updates.size();
289     }
290
291     public int numberOfInsertions() {
292         return insertions.size();
293     }
294
295     public void sortCollectionActions() {
296         if ( session.getFactory().getSettings().isOrderUpdatesEnabled() ) {
297             //sort the updates by fk
298
java.util.Collections.sort( collectionCreations );
299             java.util.Collections.sort( collectionUpdates );
300             java.util.Collections.sort( collectionRemovals );
301         }
302     }
303
304     public void sortUpdateActions() {
305         if ( session.getFactory().getSettings().isOrderUpdatesEnabled() ) {
306             //sort the updates by pk
307
java.util.Collections.sort( updates );
308         }
309     }
310
311     public ArrayList JavaDoc cloneDeletions() {
312         return (ArrayList JavaDoc) deletions.clone();
313     }
314
315     public void clearFromFlushNeededCheck(int previousCollectionRemovalSize) {
316         collectionCreations.clear();
317         collectionUpdates.clear();
318         updates.clear();
319         // collection deletions are a special case since update() can add
320
// deletions of collections not loaded by the session.
321
for ( int i = collectionRemovals.size()-1; i >= previousCollectionRemovalSize; i-- ) {
322             collectionRemovals.remove(i);
323         }
324     }
325
326     public boolean hasAnyQueuedActions() {
327         return updates.size() > 0 ||
328                 insertions.size() > 0 ||
329                 deletions.size() > 0 ||
330                 collectionUpdates.size() > 0 ||
331                 collectionRemovals.size() > 0 ||
332                 collectionCreations.size() > 0;
333     }
334 }
335
Popular Tags