001/*
002 * (C) Copyright 2012 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Florent Guillaume
018 */
019package org.nuxeo.ecm.core.work;
020
021import java.util.concurrent.CountDownLatch;
022
023/**
024 * Simple work that just sleeps, mostly used for tests.
025 */
026public class SleepWork extends AbstractWork {
027
028    private static final long serialVersionUID = 1L;
029
030    protected long durationMillis;
031
032    protected String category;
033
034    /** used for debug. */
035    protected static transient boolean debug;
036
037    /** used for debug. */
038    protected static CountDownLatch readyLatch = new CountDownLatch(1);
039
040    /** used for debug. */
041    protected static CountDownLatch doneLatch = new CountDownLatch(1);
042
043    /** used for debug. */
044    protected static CountDownLatch startLatch = new CountDownLatch(1);
045
046    /** used for debug. */
047    protected static CountDownLatch finishLatch = new CountDownLatch(1);
048
049    /**
050     * Creates a work instance that does nothing but sleep.
051     *
052     * @param durationMillis the sleep duration
053     */
054    public SleepWork(long durationMillis) {
055        this(durationMillis, "SleepWork", false);
056    }
057
058    /**
059     * If debug is true, then the various debug* methods must be called in the proper order for the work to start and
060     * stop: {@link #debugStart}, {@link #debugFinish}.
061     *
062     * @param durationMillis the sleep duration
063     * @param debug {@code true} for debug
064     */
065    public SleepWork(long durationMillis, boolean debug) {
066        this(durationMillis, "SleepWork", debug);
067    }
068
069    public SleepWork(long durationMillis, boolean debug, String id) {
070        this(durationMillis, "SleepWork", debug, id);
071    }
072
073    public SleepWork(long durationMillis, String category, boolean debug) {
074        super();
075        init(durationMillis, category, debug);
076    }
077
078    public SleepWork(long durationMillis, String category, boolean debug, String id) {
079        super(id);
080        init(durationMillis, category, debug);
081    }
082
083    private void init(long durationMillis, String category, boolean debug) {
084        this.durationMillis = durationMillis;
085        this.category = category;
086        SleepWork.debug = debug;
087        setProgress(Progress.PROGRESS_0_PC);
088    }
089
090    @Override
091    public String getCategory() {
092        return category;
093    }
094
095    @Override
096    public String getTitle() {
097        return "Sleep " + durationMillis + " ms";
098    }
099
100    @Override
101    public void work() {
102        try {
103            doWork();
104        } catch (InterruptedException e) {
105            // restore interrupted status
106            Thread.currentThread().interrupt();
107            throw new RuntimeException(e);
108        }
109    }
110
111    protected void doWork() throws InterruptedException {
112        if (debug) {
113            setStatus("Starting sleep work");
114            readyLatch.countDown();
115            startLatch.await();
116            setStatus("Running sleep work");
117        }
118
119        for (;;) {
120            long elapsed = System.currentTimeMillis() - getStartTime();
121            if (elapsed > durationMillis) {
122                break;
123            }
124            setProgress(new Progress(100F * elapsed / durationMillis));
125
126            if (isSuspending()) {
127                durationMillis -= elapsed; // save state
128                suspended();
129                if (debug) {
130                    doneLatch.countDown();
131                    finishLatch.await();
132                }
133                return;
134            }
135
136            Thread.sleep(10);
137        }
138
139        if (debug) {
140            setStatus("Completed sleep work");
141            setProgress(Progress.PROGRESS_100_PC);
142            doneLatch.countDown();
143            finishLatch.await();
144        }
145    }
146
147    @Override
148    public String toString() {
149        return getClass().getSimpleName() + "(" + (getId().length() > 10 ? "" : (getId() + ", ")) + durationMillis
150                + "ms, " + getProgress() + ")";
151    }
152
153    public void debugWaitReady() throws InterruptedException {
154        readyLatch.await();
155    }
156
157    public void debugWaitDone() throws InterruptedException {
158        doneLatch.await();
159    }
160
161    public void debugStart() {
162        startLatch.countDown();
163    }
164
165    public void debugFinish() {
166        finishLatch.countDown();
167    }
168
169}