View Javadoc

1   /**
2    * Copyright 2005 Steve Molloy
3    * 
4    * This file is part of OV4J.
5    * 
6    * OV4J is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as
7    * published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
8    * 
9    * OV4J is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
10   * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
11   * 
12   * You should have received a copy of the GNU General Public License along with OV4J; if not, write to the Free Software
13   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14   * 
15   */
16  package org.ov4j.cache;
17  
18  import java.io.IOException;
19  import java.util.Timer;
20  import java.util.TimerTask;
21  import java.util.logging.Level;
22  import java.util.logging.Logger;
23  
24  import org.ov4j.data.ClassComparable;
25  import org.ov4j.data.Version;
26  
27  /**
28   * This is the background thread which will cache results.
29   * 
30   * @author smolloy
31   * 
32   */
33  public class DelayedCacher implements Runnable {
34  	/**
35  	 * Logger for this class
36  	 */
37  	private static final Logger			logger			= Logger.getLogger(DelayedCacher.class.getName());
38  
39  	/** Thread performing the calls. */
40  	private final MethodCaller			theCaller;
41  
42  	/** The result to be cached. */
43  	private Version<ClassComparable>	theVersion;
44  
45  	/** The timeout period after which the call is considered to have failed. */
46  	private final long					theTimeout;
47  
48  	/** The ID to use for storing the result. */
49  	private final CachedResultId		theId;
50  
51  	/** The CacheHandler. */
52  	private final CacheHandler			theCache;
53  
54  	/** Whether the ID should be added or simply committed. */
55  	private boolean						addBeforeCommit	= false;
56  
57  	/** Whether or not the call has timed out. */
58  	private boolean						timedout		= false;
59  
60  	/** Task which will set the timeout flag after the timeout period. */
61  	protected TimerTask					theTimer		= new TimerTask() {
62  															@Override
63  															public void run() {
64  																setTimedout(true);
65  															}
66  														};
67  
68  	/**
69  	 * Constructor.
70  	 * 
71  	 * @param theCaller
72  	 *            The thread making the call.
73  	 * @param theVersion
74  	 *            The result to cache.
75  	 * @param theTimeout
76  	 *            The timeout period.
77  	 * @param theId
78  	 *            The ID to use for storing the result.
79  	 * @param theCache
80  	 *            The CacheHandler.
81  	 * @param addBeforeCommit
82  	 *            Whether or not the ID should be added as well as the result committed.
83  	 */
84  	public DelayedCacher(final MethodCaller theCaller, final Version<ClassComparable> theVersion,
85  		final long theTimeout, final CachedResultId theId, final CacheHandler theCache, final boolean addBeforeCommit) {
86  		this.theCaller = theCaller;
87  		this.theVersion = theVersion;
88  		this.theTimeout = theTimeout;
89  		this.theId = theId;
90  		this.theCache = theCache;
91  		this.addBeforeCommit = addBeforeCommit;
92  	}
93  
94  	/**
95  	 * @return Returns the result.
96  	 */
97  	public Version<ClassComparable> getTheVersion() {
98  		return theVersion;
99  	}
100 
101 	/**
102 	 * @return Returns the timedout.
103 	 */
104 	public boolean hasTimedout() {
105 		return timedout;
106 	}
107 
108 	/**
109 	 * Perform caching. Will try sleeping until the method caller is done, then will cache the result.
110 	 */
111 	public void run() {
112 		if (DelayedCacher.logger.isLoggable(Level.FINER)) {
113 			DelayedCacher.logger.entering("DelayedCacher", "run()", "start");
114 		}
115 
116 		final Timer timer = new Timer();
117 		timer.schedule(theTimer, theTimeout);
118 		do {
119 			try {
120 				Thread.sleep(theTimeout / 4);
121 			} catch (final InterruptedException e) {
122 				if (DelayedCacher.logger.isLoggable(Level.FINE)) {
123 					DelayedCacher.logger.logp(Level.FINE, "DelayedCacher", "run()", "exception ignored", e);
124 				}
125 			}
126 		} while (!timedout && !theCaller.hasFailed() && theCaller.getTheResult() == null);
127 
128 		timer.cancel();
129 		final Object res = theCaller.getTheResult();
130 		if (res != null) {
131 			ClassComparable theObject = null;
132 			if (res instanceof ClassComparable) {
133 				theObject = (ClassComparable) res;
134 			} else {
135 				theObject = new ClassComparable();
136 				theObject.setTheObject(res);
137 			}
138 			if (theObject != null) {
139 				try {
140 					if (theVersion == null) {
141 						theVersion = new Version<ClassComparable>();
142 						theVersion.setAuthor(CacheHandler.CACHE_AUTHOR);
143 						theVersion.setVersionNumber(0);
144 						theVersion.setComment(CacheHandler.NORMAL_COMMENT);
145 						addBeforeCommit = true;
146 					}
147 					theVersion.setVersionedObject(theObject);
148 					if (addBeforeCommit) {
149 						theCache.addNCommit(theId, theVersion);
150 					} else {
151 						theCache.commit(theId, theVersion);
152 					}
153 				} catch (final IOException e) {
154 					if (DelayedCacher.logger.isLoggable(Level.FINE)) {
155 						DelayedCacher.logger.logp(Level.FINE, "DelayedCacher", "run()", "exception ignored", e);
156 					}
157 				} catch (final InstantiationException e) {
158 					if (DelayedCacher.logger.isLoggable(Level.FINE)) {
159 						DelayedCacher.logger.logp(Level.FINE, "DelayedCacher", "run()", "exception ignored", e);
160 					}
161 				} catch (final IllegalAccessException e) {
162 					if (DelayedCacher.logger.isLoggable(Level.FINE)) {
163 						DelayedCacher.logger.logp(Level.FINE, "DelayedCacher", "run()", "exception ignored", e);
164 					}
165 				} catch (final ClassNotFoundException e) {
166 					if (DelayedCacher.logger.isLoggable(Level.FINE)) {
167 						DelayedCacher.logger.logp(Level.FINE, "DelayedCacher", "run()", "exception ignored", e);
168 					}
169 				}
170 			}
171 		}
172 
173 		if (DelayedCacher.logger.isLoggable(Level.FINER)) {
174 			DelayedCacher.logger.exiting("DelayedCacher", "run()", "end");
175 		}
176 	}
177 
178 	/**
179 	 * @param timedout
180 	 *            The timedout to set.
181 	 */
182 	public void setTimedout(final boolean timedout) {
183 		this.timedout = timedout;
184 	}
185 }