001/*
002 * (C) Copyright 2012 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Florent Guillaume
016 */
017package org.nuxeo.ecm.core.work;
018
019import java.util.concurrent.CountDownLatch;
020
021/**
022 * Simple work that just sleeps, mostly used for tests.
023 */
024public class SleepWork extends AbstractWork {
025
026    private static final long serialVersionUID = 1L;
027
028    protected long durationMillis;
029
030    protected String category;
031
032    /** used for debug. */
033    protected static transient boolean debug;
034
035    /** used for debug. */
036    protected static CountDownLatch readyLatch = new CountDownLatch(1);
037
038    /** used for debug. */
039    protected static CountDownLatch doneLatch = new CountDownLatch(1);
040
041    /** used for debug. */
042    protected static CountDownLatch startLatch = new CountDownLatch(1);
043
044    /** used for debug. */
045    protected static CountDownLatch finishLatch = new CountDownLatch(1);
046
047    /**
048     * Creates a work instance that does nothing but sleep.
049     *
050     * @param durationMillis the sleep duration
051     */
052    public SleepWork(long durationMillis) {
053        this(durationMillis, "SleepWork", false);
054    }
055
056    /**
057     * If debug is true, then the various debug* methods must be called in the proper order for the work to start and
058     * stop: {@link #debugStart}, {@link #debugFinish}.
059     *
060     * @param durationMillis the sleep duration
061     * @param debug {@code true} for debug
062     */
063    public SleepWork(long durationMillis, boolean debug) {
064        this(durationMillis, "SleepWork", debug);
065    }
066
067    public SleepWork(long durationMillis, boolean debug, String id) {
068        this(durationMillis, "SleepWork", debug, id);
069    }
070
071    public SleepWork(long durationMillis, String category, boolean debug) {
072        super();
073        init(durationMillis, category, debug);
074    }
075
076    public SleepWork(long durationMillis, String category, boolean debug, String id) {
077        super(id);
078        init(durationMillis, category, debug);
079    }
080
081    private void init(long durationMillis, String category, boolean debug) {
082        this.durationMillis = durationMillis;
083        this.category = category;
084        SleepWork.debug = debug;
085        setProgress(Progress.PROGRESS_0_PC);
086    }
087
088    @Override
089    public String getCategory() {
090        return category;
091    }
092
093    @Override
094    public String getTitle() {
095        return "Sleep " + durationMillis + " ms";
096    }
097
098    @Override
099    public void work() {
100        try {
101            doWork();
102        } catch (InterruptedException e) {
103            // restore interrupted status
104            Thread.currentThread().interrupt();
105            throw new RuntimeException(e);
106        }
107    }
108
109    protected void doWork() throws InterruptedException {
110        if (debug) {
111            setStatus("Starting sleep work");
112            readyLatch.countDown();
113            startLatch.await();
114            setStatus("Running sleep work");
115        }
116
117        for (;;) {
118            long elapsed = System.currentTimeMillis() - getStartTime();
119            if (elapsed > durationMillis) {
120                break;
121            }
122            setProgress(new Progress(100F * elapsed / durationMillis));
123
124            if (isSuspending()) {
125                durationMillis -= elapsed; // save state
126                suspended();
127                if (debug) {
128                    doneLatch.countDown();
129                    finishLatch.await();
130                }
131                return;
132            }
133
134            Thread.sleep(10);
135        }
136
137        if (debug) {
138            setStatus("Completed sleep work");
139            setProgress(Progress.PROGRESS_100_PC);
140            doneLatch.countDown();
141            finishLatch.await();
142        }
143    }
144
145    @Override
146    public String toString() {
147        return getClass().getSimpleName() + "(" + (getId().length() > 10 ? "" : (getId() + ", ")) + durationMillis
148                + "ms, " + getProgress() + ")";
149    }
150
151    public void debugWaitReady() throws InterruptedException {
152        readyLatch.await();
153    }
154
155    public void debugWaitDone() throws InterruptedException {
156        doneLatch.await();
157    }
158
159    public void debugStart() {
160        startLatch.countDown();
161    }
162
163    public void debugFinish() {
164        finishLatch.countDown();
165    }
166
167}