001: /*
002: * File : $Source: /usr/local/cvs/opencms/src/org/opencms/publish/CmsPublishQueue.java,v $
003: * Date : $Date: 2008-02-27 12:05:27 $
004: * Version: $Revision: 1.6 $
005: *
006: * This library is part of OpenCms -
007: * the Open Source Content Management System
008: *
009: * Copyright (c) 2002 - 2008 Alkacon Software GmbH (http://www.alkacon.com)
010: *
011: * This library is free software; you can redistribute it and/or
012: * modify it under the terms of the GNU Lesser General Public
013: * License as published by the Free Software Foundation; either
014: * version 2.1 of the License, or (at your option) any later version.
015: *
016: * This library is distributed in the hope that it will be useful,
017: * but WITHOUT ANY WARRANTY; without even the implied warranty of
018: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: * Lesser General Public License for more details.
020: *
021: * For further information about Alkacon Software GmbH, please see the
022: * company website: http://www.alkacon.com
023: *
024: * For further information about OpenCms, please see the
025: * project website: http://www.opencms.org
026: *
027: * You should have received a copy of the GNU Lesser General Public
028: * License along with this library; if not, write to the Free Software
029: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
030: */
031:
032: package org.opencms.publish;
033:
034: import org.opencms.db.CmsDbContext;
035: import org.opencms.db.CmsDriverManager;
036: import org.opencms.file.CmsObject;
037: import org.opencms.main.CmsException;
038: import org.opencms.main.CmsLog;
039: import org.opencms.main.OpenCms;
040:
041: import java.util.ArrayList;
042: import java.util.Collections;
043: import java.util.Iterator;
044: import java.util.List;
045:
046: import org.apache.commons.collections.Buffer;
047: import org.apache.commons.collections.BufferUtils;
048: import org.apache.commons.collections.buffer.TypedBuffer;
049: import org.apache.commons.collections.buffer.UnboundedFifoBuffer;
050: import org.apache.commons.logging.Log;
051:
052: /**
053: * This queue contains all not jet started publish jobs.<p>
054: *
055: * @author Michael Moossen
056: *
057: * @version $Revision: 1.6 $
058: *
059: * @since 6.5.5
060: */
061: public class CmsPublishQueue {
062:
063: /** The log object for this class. */
064: private static final Log LOG = CmsLog
065: .getLog(CmsPublishHistory.class);
066:
067: /** The publish engine. */
068: protected final CmsPublishEngine m_publishEngine;
069:
070: /**
071: * Default constructor, for an empty queue.<p>
072: *
073: * @param publishEngine the publish engine instance
074: */
075: protected CmsPublishQueue(final CmsPublishEngine publishEngine) {
076:
077: m_publishEngine = publishEngine;
078: }
079:
080: /**
081: * Creates the buffer used as publish queue.<p>
082: *
083: * @return the queue buffer
084: */
085: public static Buffer getQueue() {
086:
087: return BufferUtils.synchronizedBuffer(TypedBuffer.decorate(
088: new UnboundedFifoBuffer() {
089:
090: /** The serialization version id constant. */
091: private static final long serialVersionUID = 606444342980861724L;
092:
093: /**
094: * Called when the queue is full to remove the oldest element.<p>
095: *
096: * @see org.apache.commons.collections.buffer.BoundedFifoBuffer#remove()
097: */
098: public Object remove() {
099:
100: CmsPublishJobInfoBean publishJob = (CmsPublishJobInfoBean) super
101: .remove();
102: return publishJob;
103: }
104: }, CmsPublishJobInfoBean.class));
105: }
106:
107: /**
108: * Aborts the given publish job.<p>
109: *
110: * @param publishJob the publish job to abort
111: *
112: * @return <code>true</code> if the publish job was found
113: */
114: protected boolean abortPublishJob(CmsPublishJobInfoBean publishJob) {
115:
116: if (OpenCms.getMemoryMonitor().getCachedPublishJob(
117: publishJob.getPublishHistoryId().toString()) != null) {
118: // remove publish job from cache
119: OpenCms.getMemoryMonitor().uncachePublishJob(publishJob);
120: return true;
121: } else {
122: return false;
123: }
124: }
125:
126: /**
127: * Pushes a new publish job with the given information in publish queue.<p>
128: *
129: * If possible, the publish job starts immediately.<p>
130: *
131: * @param publishJob the publish job to enqueue
132: *
133: * @throws CmsException if something goes wrong
134: */
135: protected void add(CmsPublishJobInfoBean publishJob)
136: throws CmsException {
137:
138: publishJob.enqueue();
139:
140: // add publish job to cache
141: OpenCms.getMemoryMonitor().cachePublishJob(publishJob);
142:
143: // add job to database if necessary
144: if (OpenCms.getMemoryMonitor().requiresPersistency()) {
145: CmsDbContext dbc = m_publishEngine.getDbContextFactory()
146: .getDbContext();
147: try {
148: m_publishEngine.getDriverManager().createPublishJob(
149: dbc, publishJob);
150: } finally {
151: dbc.clear();
152: }
153: }
154: }
155:
156: /**
157: * Returns an unmodifiable list representation of this queue.<p>
158: *
159: * @return a list of {@link CmsPublishJobEnqueued} objects
160: */
161: protected List asList() {
162:
163: List cachedPublishJobs = OpenCms.getMemoryMonitor()
164: .getAllCachedPublishJobs();
165: List result = new ArrayList(cachedPublishJobs.size());
166: Iterator it = cachedPublishJobs.iterator();
167: while (it.hasNext()) {
168: CmsPublishJobInfoBean publishJob = (CmsPublishJobInfoBean) it
169: .next();
170: result.add(new CmsPublishJobEnqueued(publishJob));
171: }
172: return Collections.unmodifiableList(result);
173: }
174:
175: /**
176: * Initializes the internal FIFO queue with publish jobs from the database.<p>
177: *
178: * @param adminCms an admin cms object
179: * @param revive <code>true</code> if the publish queue should be revived from the database
180: */
181: protected void initialize(CmsObject adminCms, boolean revive) {
182:
183: CmsDriverManager driverManager = m_publishEngine
184: .getDriverManager();
185:
186: try {
187: OpenCms.getMemoryMonitor().flushPublishJobs();
188: if (revive) {
189: // read all pending publish jobs from the database
190: CmsDbContext dbc = m_publishEngine
191: .getDbContextFactory().getDbContext();
192: List publishJobs;
193: try {
194: publishJobs = driverManager.readPublishJobs(dbc,
195: 0L, 0L);
196: } finally {
197: dbc.clear();
198: dbc = null;
199: }
200: for (Iterator i = publishJobs.iterator(); i.hasNext();) {
201: CmsPublishJobInfoBean job = (CmsPublishJobInfoBean) i
202: .next();
203: dbc = m_publishEngine.getDbContextFactory()
204: .getDbContext();
205: if (!job.isStarted()) {
206: // add jobs not already started to queue again
207: try {
208: job.revive(adminCms, driverManager
209: .readPublishList(dbc, job
210: .getPublishHistoryId()));
211: m_publishEngine.lockPublishList(job);
212: OpenCms.getMemoryMonitor().cachePublishJob(
213: job);
214: } catch (CmsException exc) {
215: // skip job
216: if (LOG.isErrorEnabled()) {
217: LOG
218: .error(
219: Messages
220: .get()
221: .getBundle()
222: .key(
223: Messages.ERR_PUBLISH_JOB_INVALID_1,
224: job
225: .getPublishHistoryId()),
226: exc);
227: }
228: m_publishEngine.getDriverManager()
229: .deletePublishJob(dbc,
230: job.getPublishHistoryId());
231: } finally {
232: dbc.clear();
233: }
234: } else {
235: try {
236: // remove locks, set finish info and move job to history
237: job.revive(adminCms, driverManager
238: .readPublishList(dbc, job
239: .getPublishHistoryId()));
240: m_publishEngine.unlockPublishList(job);
241: new CmsPublishJobEnqueued(job).m_publishJob
242: .finish();
243: m_publishEngine.getPublishHistory()
244: .add(job);
245: } catch (CmsException exc) {
246: LOG.error(exc.getLocalizedMessage(), exc);
247: }
248: }
249: }
250: }
251: } catch (CmsException exc) {
252: if (LOG.isErrorEnabled()) {
253: LOG.error(exc.getLocalizedMessage(), exc);
254: }
255: }
256: }
257:
258: /**
259: * Checks if the queue is empty.<p>
260: *
261: * @return <code>true</code> if the queue is empty
262: */
263: protected boolean isEmpty() {
264:
265: return ((OpenCms.getMemoryMonitor() == null) || (OpenCms
266: .getMemoryMonitor().getFirstCachedPublishJob() == null));
267: }
268:
269: /**
270: * Returns the next publish job to be published, removing it
271: * from the queue, or <code>null</code> if the queue is empty.<p>
272: *
273: * @return the next publish job to be published
274: */
275: protected CmsPublishJobInfoBean next() {
276:
277: CmsPublishJobInfoBean publishJob = OpenCms.getMemoryMonitor()
278: .getFirstCachedPublishJob();
279: if (publishJob != null) {
280: OpenCms.getMemoryMonitor().uncachePublishJob(publishJob);
281: }
282: return publishJob;
283: }
284:
285: /**
286: * Removes the given job from the list.<p>
287: *
288: * @param publishJob the publish job to remove
289: *
290: * @throws CmsException if something goes wrong
291: */
292: protected void remove(CmsPublishJobInfoBean publishJob)
293: throws CmsException {
294:
295: // signalize that job will be removed
296: m_publishEngine.publishJobRemoved(publishJob);
297:
298: // remove publish job from cache
299: OpenCms.getMemoryMonitor().uncachePublishJob(publishJob);
300:
301: // remove job from database if neccessary
302: if (OpenCms.getMemoryMonitor().requiresPersistency()) {
303: CmsDbContext dbc = m_publishEngine.getDbContextFactory()
304: .getDbContext();
305: try {
306: m_publishEngine.getDriverManager().deletePublishJob(
307: dbc, publishJob.getPublishHistoryId());
308: } finally {
309: dbc.clear();
310: }
311: }
312: }
313:
314: /**
315: * Updates the given job in the list.<p>
316: *
317: * @param publishJob the publish job to
318: *
319: * @throws CmsException if something goes wrong
320: */
321: protected void update(CmsPublishJobInfoBean publishJob)
322: throws CmsException {
323:
324: if (OpenCms.getMemoryMonitor().requiresPersistency()) {
325: CmsDbContext dbc = m_publishEngine.getDbContextFactory()
326: .getDbContext();
327: try {
328: m_publishEngine.getDriverManager().writePublishJob(dbc,
329: publishJob);
330: } finally {
331: dbc.clear();
332: }
333: }
334: }
335: }
|